【问题标题】:printing after splitting a line of text at delimiters在分隔符处分割一行文本后打印
【发布时间】:2016-08-04 13:59:31
【问题描述】:

我无法打印这个。当我要求用户插入 int 时,它起作用了,但是当尝试将其切换到 char 输入时,它变得很糟糕,不会打印任何东西。

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

int main() {
    const char delim[2] = ",";
    char *token;
    int j = 0;
    char *hh;
    FILE *ptr_file;
    char buf[1000];

    ptr_file = fopen("input.txt", "r");
    if (!ptr_file)
        return 1;

    char *pt[] = { "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na" };

    printf("what element do you want(Use atomic number)");
    scanf("%s", &hh);

    for (j = 0; j <= 3; j++) {
        if (hh == pt[j]) {
            fgets(buf, 1000, ptr_file);
            token = strtok(buf, delim);
            while (token != NULL) {
                printf("%s\n", token);
                token = strtok(NULL, delim);
            }
            break;
        } else {
            fgets(buf, 1000, ptr_file);
            continue;
        }
    }

    fclose(ptr_file);
    return 0;
}

【问题讨论】:

    标签: c pointers scanf


    【解决方案1】:

    这里的主要问题是,您将scanf() 传递给未初始化指针hh 的地址。 scanf 调用未定义的行为,试图将单词存储在该地址。

    您应该将hh 设为一个数组,如char hh[8] = {0}; 并以这种方式使用scanf()

     scanf("%7s", hh);  // to avoid buffer overflow
    

    也就是说,

    • if(hh == pt[j]) 不是比较字符串的方法。您需要使用strcmp() 来执行此操作,并编写if (strcmp(hh, pt[j]) == 0)
    • 您还应该检查scanf() 的返回值,以验证输入是否正确转换。

    【讨论】:

    • 那我该怎么做呢?
    【解决方案2】:

    代码

    char  *hh;
    //...
    scanf("%s", &hh);
    

    它是UB 由于hh 未初始化:它指向垃圾。 此外,"%s" 格式说明符希望 char * 作为传递参数:您正在传递 char **

    应该是

    char  *hh = malloc(MAX_STRING_LEN);
    if (hh != NULL)
    {
       //...
       scanf("%s", hh);
    }
    free(hh);
    

    或者干脆

    char  hh[MAX_STRING_LEN] = {0};
    //...
    scanf("%s", hh);
    

    在这两个例子中,MAX_STRING_LEN 表示最大可接受的字符串长度 + 1 作为空终止符。


    使用你不能使用逻辑运算符==比较字符串,所以代码

    if(hh == pt[j])
    

    比较的是地址而不是字符串。 您可以使用strcmp 来执行此操作。

    【讨论】:

    • 我试过但报错。错误:'MAX_STRING_LEN' undeclared (first use in this function) char hh[MAX_STRING_LEN] = {0};
    • @christian MAX_STRING_LEN 只是一个指标,表明您应该输入所需的最大字符串长度。
    • 如果scanf 有类似于printf 的语义就好了……不幸的是,scanf("%*s", MAX_STRING_LEN-1, hh); 只会解析一个单词并丢弃它。 * 表示不存储。指定要存储的最大字符数的唯一方法是在格式字符串中使用明确的数字。
    • 您仍然应该通过硬编码一些大小来保护目的地。丑陋但安全。
    • @chqrlie 我会使用 fgets ;)
    猜你喜欢
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多