【问题标题】:isspace not working correctly?isspace 不能正常工作?
【发布时间】:2014-11-25 06:14:10
【问题描述】:

这可能是我的代码不起作用,但任何空白字符(\n、\t、\r 等)都没有被转换为空格“”。据我所见,它看起来应该可以工作,但是每次遇到新行时都会出现段错误。

编辑:对不起,它确实将空白字符更改为'',但在新行被击中后它会停止。然后程序运行代码直到新的行点——它出现了段错误。

它也不会替换任何空格。 代码绘制在一个 .txt 文件中,因此如果要运行它,请创建一个名为 alice.txt 的文本文件(或者您可以更改代码)并在文件中包含空格字符。

你能帮帮我吗,我已经尝试解决这个问题好几个小时了,但无济于事。我究竟做错了什么?谢谢!

#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

#define LEN 4096

void upper(char *tok, FILE *out);
void rstrip(char *tok, FILE *out);

int main ()
{
    char *tok;  //tokenizer
    char buf[LEN];
    FILE *in = fopen("alice.txt", "r");
    FILE *out = fopen("out.txt", "w");
    int len = 0;

    while (fgets(buf, LEN, in)) {
        /* cleans all line breaks, tabs, etc, into space*/
        while (buf[len]) {
            printf("%c", buf[len]); //Error checking, prints each char of buf
            if (isspace(buf[len]))  //isspace not working properly? not changing \t, \r, etc to ' ' */
                buf[len] = ' ';     //not replacing
            if (buf[len] < 0)   //added cuz negative character values were being found in text file.
                buf[len] = ' '; 
            len++;
        }

        /*parses by words*/
        tok = strtok(buf, " ");
        rstrip(tok, out);
        while (tok != NULL) {
            tok = strtok(NULL, " ");
            rstrip(tok, out);
        }
    }

    fclose(in);
    fclose(out);
    return 0; 
}

/*makes appropiate words uppercase*/
void upper(char *tok, FILE *out)
{
    int cur = strlen(tok) - 1; //current place

    while (cur >= 0) {
        tok[cur] = toupper(tok[cur]);
        printf("%s\n", tok); 
        fprintf(out, "%s", tok);
        cur--;
    }

}

/*checks for 'z' in tok (the word)*/
void rstrip(char *tok, FILE *out)
{
    int cur = strlen(tok) - 1; //current place

    printf("%s", tok);
    while (cur >= 0) {
        if (tok[cur] == 'z')
            upper(tok, out);
        cur--;
    }
}

【问题讨论】:

  • 您应该在第一次循环后将变量 len 初始化回 0。也开始使用调试器
  • 您的第二个 strtok(带有NULL 的那个)应该在rstrip 调用之后,否则您将跳过第一个令牌(而不是终止循环正确)。 isspace 运行良好。您遇到任何问题的原因都在其他地方。
  • if (buf[len] &lt; 0) 这只有在FILE *in = fopen("alice.txt", "r"); 失败时才会发生。在读取之前验证文件是否已打开。 (例如if (!in) { printf ("error: open failed\n"; return 1; }。这将防止从文本文件中读取奇怪个字符。在写入之前对out执行相同操作。
  • @DavidC.Rankin:我不确定那个。如果您的机器使用有符号字符,buf 中很可能会有否定条目。所有不代表 ASCII 的 UTF-8 序列都将由负符号字符组成。 (当然,它们应该表示为uint8_t。)在Latin1 中,否定字符不称为strange,而是称为accented
  • 好的,我给你那个。我在考虑 alice.txt 将包含标准的 ASCII 文本。如果 alice.txt 是 UTF-8,那么这个假设需要重新考虑。如果我们知道alice.txt 中的内容,那么我们肯定会知道。但是,这些都不会降低验证建议的正确性。

标签: c file ctype


【解决方案1】:

您将len = 0; 设置在错误的位置。

你需要:

while (fgets(buf, LEN, in) != 0)
{
    for (int len = 0; buf[len] != '\0'; len++)
    {
        printf("%c", buf[len]);
        if (isspace((unsigned char)buf[len]))
            buf[len] = ' ';
        if (buf[len] < 0)
            buf[len] = ' ';
    }
    …rest of loop…
}

这可确保您将所读取的每一行的 len 设置为 0。您还需要确保isspace() 的参数有效——这意味着它是int,并且必须是EOF 或与unsigned char 对应的值。

C 标准说(参考&lt;ctype.h&gt;is*() 函数的参数:

在所有情况下,参数都是int,其值应为 可表示为 unsigned char 或应等于宏 EOF 的值。

【讨论】:

  • @RolandIllig:是的;固定。
【解决方案2】:

除了验证您的FILE *streams 是否打开之外,您还需要验证传递给您的函数的值。当strtok 完成标记化时,它返回NULL。您不想将NULL 传递给rstrip。例如:

void rstrip(char *tok, FILE *out)
{
    if (!tok) return;          // validate tok

    int cur = strlen(tok) - 1; //current place

您需要对upper 执行相同的操作。简单地解决这些问题会有很长的路要走。在合并 J.L. 建议的验证和更改后:

输入:

$ cat alice.txt
#include <stdio.h>
int func()
{
z z z z z
}
int main(void)
{
    printf("%d\n",func());
    return 0;
}

输出:

$ ./bin/ctypehelp
#include <stdio.h>
#include<stdio.h>int func()
intfunc(){
{ z z z z z
zZ
zZ
zZ
zZ
zZ
}
}int main(void)
intmain(void){
{    printf("%d\n",func());
printf("%d\n",func());    return 0;
return0;}

out.txt:

$ cat out.txt
ZZZZZ

进行这些改进并在您再次遇到困难时回复。

【讨论】:

    猜你喜欢
    • 2015-07-08
    • 2013-03-30
    • 2010-11-30
    • 2021-10-02
    • 2017-08-06
    • 2013-11-22
    • 1970-01-01
    • 2013-09-10
    • 2017-04-05
    相关资源
    最近更新 更多