【问题标题】:C - Malloc issue (maybe something else)C - Malloc问题(也许是别的)
【发布时间】:2011-05-18 22:13:07
【问题描述】:

更新版本:

所以,我试图让这段代码在不使用 scanf/fgets 的情况下工作。从用户获取字符,使用嵌套在 for 循环中的 while 循环将其放入指针数组中。

#define WORDLENGTH 15 #define MAXLINE 1000 主函数() { 字符 *line[MAXLINE]; 诠释 i = 0; 诠释 j; 诠释n; 字符 c; 对于 (n=0; c!=EOF; n){ char *tmp = (char *) malloc(256); 而 ((c=getchar())!=' '){ tmp[i]=c; // 由于某种原因不再更新。 我++; } 行[n++]=tmp; // 我=0; printf("\n%s\n",line[n]); //这里的段错误 } for(j = 0; j (小于) n; j++){ printf("\n%s\n", line[j]); 免费(线[j]); } 返回0;

所以,现在我遇到了段错误。不知道为什么 tmp[i] 没有正确更新。仍在努力。

到目前为止,我在整个学期中从未学到这么多关于编程的知识。请继续帮助我学习。我喜欢这个。

【问题讨论】:

    标签: c arrays malloc


    【解决方案1】:

    您打印line[i],而在此之前,您将i 设置为0。改为打印line[n]

    另外,您忘记了终止字符 0。如果您将 tmp 设为 char 数组,然后将 strdup 分配给 line[n],您的代码将变得更容易。

    【讨论】:

    • 终止 0 个字符?你的意思是\0?
    • 由于'\0' == 0,我一般用后者:)
    【解决方案2】:

    sizeof(WORLDLENGTH) 一方面是错误的。 malloc 接受一个整数,而 WORLDLENGTH 是一个整数。 sizeof(WORLDLENGTH) 将为您提供一个整数的大小,如果您为 32 位系统编译,则为 4,因此您分配了 4 个字节。

    顺便说一句 - while ((c=getchar())!=' '||c!=EOF) - 你在这里的意图是什么?如果 b!=c,像 (a!=b || a!=c) 这样的条件将始终返回 true,因为 a 不可能同时是 b 和 c。

    而且,正如其他人指出的那样,您正在打印出line[i],其中 i 始终为 0。您的意思可能是 line[n]。而且你不会终止 tmp 字符串。

    而且没有溢出检查,所以如果一个词长于 WORDLENGTH,你就会遇到邪恶的错误。

    【讨论】:

    • 啊啊啊,我完全忘记了,但我不会再来了!虽然仍然遇到同样的问题=\
    • 是的需要做 malloc(sizeof(char)*WORDLENGTH);
    • 是的,malloc(WORDLENGTH) 就足够了。顺便说一句,我编辑了我的答案以添加更多问题。
    • 好吧,如果标准 sizeof(char) == 1,那么它会起作用,但我对 C 的记忆是,每个编译器在很多事情上都按照自己的感觉去做,哈哈 + 这是避免的好习惯当您更改为浮动列表或加倍而您忘记时出现问题。
    • 防御性编程 - 确保保护自己免受任何可能导致应用崩溃的问题,尤其是在处理用户输入时。
    【解决方案3】:

    其他人已经告诉过您的代码存在一些具体问题,但他们似乎遗漏了一件事情,那就是 c 应该是 int,而不是 char。否则与EOF 的比较将无法按预期进行。

    另外,你得到的段错误是因为这个序列:

    line[n++]=tmp;
    printf("\n%s\n",line[n]);
    

    已经n 增加到下一个数组元素,然后您尝试打印它。第二行应该是:

    printf("\n%s\n",line[n-1]);
    

    如果您只想要一些有效的代码(使用免费的“做你想做的事”许可证),这里有一个来自我的代码库的有用的 sn-p。

    我不确定为什么您认为应该避免使用fgets,它实际上非常方便且非常安全。我假设您的意思是gets,它不太方便且完全不安全。您的代码也容易出现缓冲区溢出,因为如果它得到很多既不是空格也不是文件结尾的字符,它会很高兴地写入超出分配区域的末尾。

    如果您正在自学,请务必编写自己的代码,但其中一部分应该是检查经过生产测试的防弹代码,以了解它是如何完成的。而且,如果您自学,那么不使用免费提供的代码就是在伤害自己。

    sn-p 如下:

    #include <stdio.h>
    #include <string.h>
    
    #define OK       0
    #define NO_INPUT 1
    #define TOO_LONG 2
    static int getLine (char *prmpt, char *buff, size_t sz) {
        int ch, extra;
    
        // Get line with buffer overrun protection.
        if (prmpt != NULL) {
            printf ("%s", prmpt);
            fflush (stdout);
        }
        if (fgets (buff, sz, stdin) == NULL)
            return NO_INPUT;
    
        // If it was too long, there'll be no newline. In that case, we flush
        // to end of line so that excess doesn't affect the next call.
        if (buff[strlen(buff)-1] != '\n') {
            extra = 0;
            while (((ch = getchar()) != '\n') && (ch != EOF))
                extra = 1;
            return (extra == 1) ? TOO_LONG : OK;
        }
    
        // Otherwise remove newline and give string back to caller.
        buff[strlen(buff)-1] = '\0';
        return OK;
    }
    

     

    // Test program for getLine().
    
    int main (void) {
        int rc;
        char buff[10];
    
        rc = getLine ("Enter string> ", buff, sizeof(buff));
        if (rc == NO_INPUT) {
            printf ("No input\n");
            return 1;
        }
    
        if (rc == TOO_LONG) {
            printf ("Input too long\n");
            return 1;
        }
    
        printf ("OK [%s]\n", buff);
    
        return 0;
    }
    

    这是一个有用的行输入功能,具有与fgets相同的缓冲区溢出保护,还可以检测用户输入的过长行。它还会丢弃剩余的过长行,以免影响下一个输入操作。

    使用 'hello'、CTRLD 和太大的字符串运行示例:

    pax> ./qq
    Enter string> hello
    OK [hello]
    
    pax> ./qq
    Enter string>
    No input
    
    pax> ./qq
    Enter string> dfgdfgjdjgdfhggh
    Input too long
    
    pax> _
    

    为了它的价值(不要把它作为你自己的工作上交,因为你几乎肯定会因为抄袭而被抓到 - 任何半像样的教育工作者都会在网上搜索你的代码作为他们做的第一件事),这就是我的处理方式。

    #include <stdio.h>
    #include <stdlib.h>
    
    #define WORDLENGTH 15
    #define MAXWORDS 1000
    
    int main (void) {
        char *line[MAXWORDS];
        int numwords = 0;  // Use decent variable names.
        int chr, i;
    
        // Code to run until end of file.
    
        for (chr = getchar(); chr != EOF;) {           // First char.
            // This bit gets a word.
    
            char *tmp = malloc(WORDLENGTH + 1);        // Allocate space for word/NUL
            i = 0;
            while ((chr != ' ') && (chr != EOF)) {     // Read until space/EOF
                if (i < WORDLENGTH) {                  // If space left in word,
                    tmp[i++] = chr;                    //   add it
                    tmp[i] = '\0';                     //   and null-terminate.
                }
                chr = getchar();                       // Get next character.
            }
            line[numwords++] = tmp;                    // Store.
    
            // This bit skips space at end of word.
    
            while ((chr == ' ') && (chr != EOF)) {
                chr = getchar();
            }
        }
    
        // Now we have all our words, print them.
    
        for (i = 0; i < numwords; i++){
            printf ("%s\n", line[i]);
            free (line[i]);
        }
    
        return 0;
    }
    

    我建议您阅读并研究 cmets,以便了解它是如何工作的。欢迎在 cmets 部分提出任何问题,我会回答或澄清。


    这是一个示例运行:

    pax$ echo 'hello   my name is pax andthisisaverylongword here' | ./testprog
    hello
    my
    name
    is
    pax
    andthisisaveryl
    here
    

    【讨论】:

    • 我不想在我们不应该使用 fgets 的作业中使用它,因为老师出于某种原因不喜欢你获得帮助并且人们为你提供的答案是比他们目前教你的更有用。他们为什么这样做我不知道。我真的很感激这个例子!比我拥有的要好得多,但是,我必须在这种情况下继续努力。我想被困在盒子里也是一种很好的编程习惯=\
    • 那么,我将提供一条非常宝贵的建议。 知道您分配了多少内存并知道您已经写入了多少内存。 永远不要让后者超过前者 :-) 无论如何,我都会为自己研究的学生鼓掌。查看fgets 并理解它。如果您被要求,您将能够在这种情况下捍卫您的选择。如果一位教育工作者因为我比他们了解更多而对我进行了评分,我会向教育机构提出这一点。 YMMV。
    • 也许这就是我现在遇到分段错误的原因? =\ 它非常接近工作,然后我更改了代码:Seg fault。改回来?段错误。为什么yyyyyyyyyy
    • 按原样完全发布当前代码,在另一个问题中,“为什么此代码会导致分段违规”。然后放松大约 2 分钟让蜂群攻击它:-)
    • 非常感谢您的更新!我会确保你的工作不会白费!
    【解决方案4】:

    更改您的 printf 行 - 您需要打印 line[n] 而不是 line[i]

    【讨论】:

      【解决方案5】:

      首先你的 malloc 公式是错误的

       malloc(sizeof(char)*WORDLENGTH);
      

      您需要为单词的长度分配足够多的字符大小(也 15 似乎有点小,您不计算字典中最长的单词或“iforgettoputspacesinmyphrasestoscrewtheprogrammer”情况哈哈 不要害羞 char 很小,你可以轻松达到 256 或 512 ^^

      还有

       printf("\n%s\n",line[i]);
      

      需要改成

      int j = 0;

      for(j=0;j<i;j++){
           printf("\n%s\n",line[j]);
      }
      

      你的 i 永远不会改变,所以你总是打印同一行

      【讨论】:

      • 我不确定!我害怕潜在地分配太多内存?我会确保解决这个问题。
      猜你喜欢
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多