【问题标题】:sscanf cycle segmentation faultsscanf 循环分段错误
【发布时间】:2017-08-01 09:17:44
【问题描述】:

我已经有几年没有编程了,我有一个问题要问sscanf

我想使用sscanf 将一个字符串分成几个,但是sscanf 在一个循环中给了我分段错误。这是为什么?我怎样才能在一个循环中使用sscanf 而不会发生?

例子:

int main() {
    char str[100];
    char mat[100][100]; int i = 0;
    strcpy(str, "higuys\nilovestackoverflow\n2234\nhaha");

    while (sscanf(str, "%s", mat[i]) == 1) i++;  
}

【问题讨论】:

  • 把这个:while(sscanf(str,"%s", mat[i]) == 1); i++; 改成这个:while(sscanf(str,"%s", mat[i]) == 1) i++;
  • 别忘了在 strcpy 行的字符串后面加上一个 "。
  • 这里有一个错字。您的代码只是一个无限循环。它不会/不能出现段错误。
  • 这就是我们复制/粘贴而不是重新输入源的原因。如果您不提供minimal reproducible example,我们将无法帮助您解决问题
  • @Jean-FrançoisFabre 原始代码在 while 之后有一个杂散的 ;,这意味着 while 循环不包含增量语句。

标签: c segmentation-fault cycle scanf


【解决方案1】:

int sscanf(const char *str, const char *format, ...);

while(sscanf(str,"%s",  mat[i]) == 1)  i++;

由于str 在原型中是常量,它不能sscanf 更改(除非sscanf非常 损坏:)),所以它成功地重复一遍又一遍,一直返回 1 ...... 所以i 增加了,在某些时候你会遇到内存边界,系统会停止你的有害程序。

如果您想读取多行字符串,请使用带有strtok 的循环,这将通过您的字符串并产生行。

注意:我之前的回答正确假设之前版本的问题有一个错字,中间有一个额外的;

while(sscanf(str,"%s",  mat[i]) == 1);   i++;

总是成功的,因为str 是输入并且不会改变(与使用fscanffgets 从文件读取时不同)。

所以在这种情况下它只是一个无限循环。

【讨论】:

  • 我很确定 sscanf 会在 \n 处停止,可能是程序运行时间不到 0.1 秒,所以我对此表示怀疑。
  • @MiguelS - 然后你会得到通常的重复 - 请在调试器中运行它以发现你真正的问题是什么。
  • @MiguelS: sscanf'\n' 处停止,将单词higuys 存储到数组mat[i] 中并返回1。循环条件为真,i 递增,该过程继续进行,mat 的下一个元素作为具有相同源字符串的目标...mat 的每个元素都接收相同的higuys 字符串,并且循环继续,导致缓冲区溢出,调用未定义的行为并最终崩溃。
  • 是的,我以为它会在 \n 之后跳转到下一件事,我不知道我从哪里得到这个想法,是 fgets 还是 smth 这样做的?谢谢
  • fscanf 如果字符串中没有空格(如您的示例中)或fgets,则这样做。
【解决方案2】:

sscanf 停在\n,将单词higuys 存储到数组mat[i] 中并返回1。循环条件为真,i 递增,并且该过程继续将mat 的下一个元素作为具有相同源字符串的目标...mat 的每个元素都接收相同的higuys 字符串,并且循环继续,导致缓冲区溢出,调用未定义的行为并最终崩溃。

以下是如何修改代码以使其工作:

#include <stdio.h>

int main(void) {
    const char *str = "higuys\nilovestackoverflow\n2234\nhaha";
    char mat[100][100];
    int i = 0, n = 0;

    /* parse the multiline string */
    while (sscanf(str, "%s%n", mat[i], &n) == 1) { 
        str += n;
        i++;  
    }
    /* output the array */
    for (int j = 0; j < i; j++) {
        printf("mat[%d] = %s\n", j, mat[j]);
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 2016-07-27
    相关资源
    最近更新 更多