C - Malloc问题(可能还有别的)

时间:2010-12-02 04:59:22

标签: c arrays malloc

更新版本:

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

#define WORDLENGTH 15
#define MAXLINE 1000

int main()
{
    char *line[MAXLINE];
    int i = 0;
    int j;
    int n;
    char c;


    for (n=0; c!=EOF; n){
        char *tmp = (char *) malloc(256);
        while ((c=getchar())!=' '){
            tmp[i]=c;     // This is no longer updating for some reason. 
            i++;
            }
        line[n++]=tmp; // 
        i=0;
        printf("\n%s\n",line[n]); //Seg fault here
    }

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

    return 0;

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

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

5 个答案:

答案 0 :(得分:4)

您打印line[i]就在此之前,您将i设置为0.打印line[n]代替。

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

答案 1 :(得分:3)

例如,{p> sizeof(WORLDLENGTH)是错误的。 malloc取整数,WORLDLENGTH是整数。 sizeof(WORLDLENGTH)将为您提供一个整数的大小,如果您为32位系统编译,则为4,因此您将分配4个字节。

顺便说一下 - while ((c=getchar())!=' '||c!=EOF) - 你的意图是什么?如果b!= c,像(a!=b || a!=c)这样的条件总是会返回true,因为b和c都不可能同时出现。

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

首先你的malloc公式是错误的

 malloc(sizeof(char)*WORDLENGTH);

你需要为你的单词长度分配一个字符的大小(也有15个似乎有点小,你不计算字典中最长的单词或“iforgettoputspacesinmyphrasestoscrewtheprogrammer”案例lol 不要害羞char很小你可以轻松打到256或512 ^^

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

需要更改为

int j = 0;

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

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

答案 4 :(得分:1)

其他人已经告诉过您代码的一些具体问题,但他们似乎错过了一件事c应该是int,而不是char。否则,与EOF的比较将无法按预期工作。

此外,您获得的段错是由于这个序列:

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

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

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

如果你只是想要一些有效的代码(免费“做你想做的”许可),这里是我的代码库中一个有用的代码片段。

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

无论如何,如果您正在教育自己,请编写自己的代码,但其中一部分应该检查经过生产测试的防弹代码,以了解可以如何完成。而且,如果你自我教育,那么你就不会因为不使用免费的代码而伤害自己。

该片段如下:

#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', CTRL D 运行,并且字符串太大了:

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;
}

我建议你阅读并仔细阅读评论,以便了解它是如何工作的。请随意在评论部分提出任何问题,我会回答或澄清。


这是一个示例运行:

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