【问题标题】:C: search for non-number-character in arrayC:在数组中搜索非数字字符
【发布时间】:2017-10-25 13:50:50
【问题描述】:

我正在构建一个 C 程序,它获取一个 .txt 文件作为参数。 .txt 里面有几行整数,它们之间有一个空格,像这样:

1 2 3 4
5 6 7 8
...

我应该知道,如果一个非整数字符出现在 .txt 文件中,像这样:

1 2 a 4
...

由于 C 中没有 instanceof 运算符,我使用一个包含 0-9 数字的数组,并检查 .txt 文件中的每个字符,它是空格还是整数。如果两者都不是,则程序应该退出。 如果文件中没有问题,程序会计算一个中值并将该行打印到标准输出。 这是我的代码:

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

int arrayContains(char value);

int main(int argc, char **argv) {
    const int LINESIZE = 255;
    if (argc != 2) {
        printf("wrong args!");
        return -1;
    }
    char *command1 = argv[1];
    FILE *handle = fopen(command1, "r");
    if (!handle) {
        printf("file not found!");
        return -1;
    }
    int count = 0;
    int sum = 0;
    int median;
    char string[LINESIZE];
    while (fgets(string, LINESIZE, handle) != NULL) {
        for (int i = 0; i <= sizeof(string) / sizeof(string[0]) - 1; i++) {
            printf("%c", string[i]);
            if (string[i] == ' ') {
                i++;
            }
            else if (arrayContains(string[i]) == 0) {
                count++;
                sum += (int)string[i];
            }
            else {
                printf("non-integer-character found!\n");
                return -1;
            }
        }
        median = sum / count;
        printf("%s\n", string);
        printf("%d\n", median);
    }
}

int arrayContains(char value) {
    const char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    for (int i = 0; i <= 9; i++) {
        if (numbers[i] == value) {
            return 0;
        }
    }
    return -1;
}

现在程序的输出始终是 txt 文件的第一个数字,紧随其后的是:“找到非整数字符!”。 这告诉我,gets() 中的字符串元素与 arrayContains() 函数内的常量“数字”数组中的元素之间的比较,将始终导致 arrayContains() 函数返回 -1。 我做错了什么?

【问题讨论】:

  • i &lt;= sizeof(string) / sizeof(string[0]) - 1; --> string[i];
  • 不相关,但没有“非整数字符”,但有“非数字字符”。

标签: c arrays character


【解决方案1】:

你真的应该看看isdigit C 函数!

#include <ctype.h>

int hasDigit(const char *s)
{
    while (*s) {
        if (isdigit(*s++) == 0) return 0;
    }

    return 1;
}

上面的代码在空字符串上返回 1。小心!您可以使用我的功能代替您的arrayContains。如果你想使用你的例程,请查看我的“版本”:

int arrayContains(char value) {
    return isdigit(value)?0:-1;
}

【讨论】:

  • 该死的,它更短! Op的解决方案其实效率低下,总体来说还不错!
  • 我看不出您的 arrayContains 和 OP 之间有任何显着差异。
  • for 循环的第二部分
  • 好的,但这并不是真正的重要,也不是更好也不是更糟,只是不同而已。
  • 好吧,现在arrayContains 真的没有意义了,为什么不先打电话给isdigit 呢?无论如何,arrayContains 的名称具有误导性。
【解决方案2】:

您的代码有几个问题。

该位匹配一个空格,但会导致您跳过以下字符,因为您的循环也会执行i++

if (string[i] == ' ') {
    i++;
}

这不是将数字转换为数字的正确方法。你在这里得到的是字符的 ASCII 值而不是数字的值。因此,例如,如果您有一个“1”,那么您将 49 加到 sum 而不是 1。

sum += (int)string[i];

正如其他地方所讨论的,您最好使用isdigit() 来识别您是否有数字字符。您还可以使用isspace() 来测试您是否有空格或“\n”字符(它涵盖了所有空格)。这将使您的循环语句不那么复杂,因为您可以处理整个字符串并轻松处理比缓冲区大小长的行。

这段代码解决了你遇到的问题

while (fgets(string, LINESIZE, handle) != NULL) {
    for (char *pos=string; *pos!='\0'; pos++) {
        printf("%c", *pos);
        if (isdigit(*pos)) {
            count++;
            sum += *pos-'0';
        } elseif(!isspace(*pos)) {
            printf("non-integer-character found!\n");
            return -1;
        }
    }
    median = sum / count;
    printf("%s\n", string);
    printf("%d\n", median);
}

【讨论】:

    【解决方案3】:

    我好像已经解决了:

    #include <stdio.h>
    #include <ctype.h>
    
    int arrayContains(char value);
    
    int main(int argc, char **argv) {
        const int LINESIZE = 255;
        if (argc != 2) {
            printf("wrong args!");
            return -1;
        }
        char *command1 = argv[1];
        FILE *handle = fopen(command1, "r");
        if (!handle) {
            printf("file not found!");
            return -1;
        }
        int count = 0;
        int sum = 0;
        int median;
        char string[LINESIZE];
        while (fgets(string, LINESIZE, handle) != NULL) {
            for (int i = 0; i <= sizeof(string) / sizeof(string[0]) - 1; i++) {
                printf("%c\n", string[i]);
                if (isspace(string[i]) == 0) {
                    i++;
                }
                else if (isdigit(string[i]) == 0) {
                    count++;
                    sum += (int)string[i];
                }
                else {
                    printf("non-integer-character found!\n");
                    return -1;
                }
            }
            fgets(string, LINESIZE, handle);
        }
        median = sum / count;
        printf("%s\n", string);
        printf("%d\n", median);
    }
    

    它现在有点像预期的那样工作了。

    【讨论】:

    • 但是您在空格后仍然跳过字符
    • 是的,我跳过了空格字符,因为我对它们不感兴趣。我只想处理整数
    • 不,我的意思是你跳过了空格......然后是字符,因为你正在做一个额外的i++
    【解决方案4】:

    您使用的运算符 sizeof() 不会返回字符串的长度,而是指针的内存大小(一个 size_t 所以 8 个字节)。

    我建议您将其用于您的 for 循环:

    for (int i = 0; string[i] != '\0' && string[i] != '\n'; i++) {
        ...
    }
    

    C 中的字符串只是内存的一部分,它就像一个数组,获得长度的唯一方法是找到结尾('\0')

    我也建议你直接搜索 ASCII 表。字符只是 0 到 127 之间的数字。数字介于 48 到 57 之间,一个简单的条件就可以了!

    if (string[i] <= 48 || string[i] >= 57) {
        ...
    }
    

    【讨论】:

    • 这并不能解决arrayConsains返回值问题
    • 你不需要arrayContains,正如Krzysztof Szewczyk所说,你可以使用isDigit或者使用Ascii table
    • (string[i] &gt; 121 &amp;&amp; string[i] &lt; 112) 永远不会是真的
    • @ChrisTurner 我认为可以。
    • @KrzysztofSzewczyk 比 121 多,又比 112 少的数是多少呢? ;)
    猜你喜欢
    • 2016-03-08
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多