繁体   English   中英

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

[英]C - Malloc issue (maybe something else)

更新版本:

所以,我试图在不使用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]没有正确更新。 仍在努力。

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

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

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

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

Btw - while ((c=getchar())!=' '||c!=EOF) - 你的意图是什么? 如果b!= c,像(a!=b || a!=c)这样的条件总是返回true,因为a和b都不可能。

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

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

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

首先你的malloc公式是错误的

 malloc(sizeof(char)*WORDLENGTH);

你需要为你的单词长度分配一个char的大小(也就是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]);
}

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

其他人已经告诉你代码的一些具体问题,但他们似乎错过的一件事是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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM