C:错误地从缓冲区复制字符串

时间:2017-04-24 08:47:51

标签: c fopen

我一直在处理文本文件,但不知何故,我遇到了一个奇怪的错误。当我尝试获取字符串的第1,第2,第4和第5部分(':'是分隔符)时,我得到一个奇怪的响应。这是我想读的内容: 1000:产品:0.75:5:0

我得到了这样的答案:

8            |X      |0
75(

以下是代码:

int main(){
char c,buff[100],prod[30],id[8],stock[8],vendas[8];
int i=0,n=0,num=0;
FILE *fp;
fp=fopen("products.txt","r+");
printf("Lista de produtos(Num |Produto |Stock |Vendas)\n");
while(fgets(buff,100,fp)){
 for(n=0;n<strlen(buff);n++){
   if(buff[n]==':'){
    num++;
    i=0;
    }       
   else if((buff[n]!=':')&&(num==0)){
    id[i]=buff[n];
    i++;
    }
   else if((buff[n]!=':')&&(num==1)){
    prod[i]=buff[n];
    i++;
    }
   else if((buff[n]!=':')&&(num==3)){
    stock[i]=buff[n];
    i++;
    }
   else if((buff[n]!=':')&&(num=4)){
    vendas[i]=buff[n];
    i++;
    }      
  }
 i=0;
 num=0;
 printf("%s   |%s              |%s      |%s\n",id,prod,stock,vendas);    
 memset(id,0,8);
 memset(prod,0,30);
 memset(stock,0,8);
 memset(vendas,0,8);
 }
printf("Prima qualquer tecla para sair");
getchar();
return 0;
}

任何帮助将不胜感激。对不起,如果这个问题或我的代码不是最好的。 祝你有美好的一天!

4 个答案:

答案 0 :(得分:0)

  • 如果格式字符串不以:开头,则永远不会初始化i
  • 如果确实以:开头,那么num==0永远不会被执行。
  • 你永远不会终止字符串。
  • if(buff[n]==':') ... else if((buff[n]!=':'是多余的。
  • num=4是一个错误,启用编译器警告或获得更好的编译器。
  • 您永远不会检查文件是否正确打开,也不会检查文件的末尾。

答案 1 :(得分:0)

最合适的时间通过调用未定义的行为,因为您尚未初始化每个字段缓冲区的内容。

填写字段时,也不检查缓冲区溢出。如果字段长于或长于您放入的数组,则会出现缓冲区溢出且没有终止\0

同样在每个else if中,您不需要(buff[n]!=':')条件。

此外,最后一个else if在条件n = 4中有一个赋值(虽然这实际上不会影响结果)。

答案 2 :(得分:0)

至少有两个错误:

在尝试使用数组之前先初始化数组...

while(fgets(buff,100,fp)){
  memset(id,0,8);
  memset(prod,0,30);
  memset(stock,0,8);
  memset(vendas,0,8);
  for(n=0;n<strlen(buff);n++){

测试中的分配,替换:

if((buff[n]!=':')&&(num=4)){

if((buff[n]!=':')&&(num==4)){
                        ^

答案 3 :(得分:0)

你可能会使逻辑变得更加困难。当您必须根据分隔符将一行文本分成单词时,您应该考虑strtokstrsepstrtok是用于标记化分隔符上的一行文本的常规例程,将行分为单个单词。 (strsep主要在有可能遇到空字段时使用,如在大型.csv文件中一样。)

您的令牌很简单':'字符和最后的'\n'。你可以简单地声明char *delim = ":\n";并被覆盖。

虽然您可以自由地将菊花链if, then, else if, ....放在一起,但计数器上的switch可以让生活更轻松,代码更具可读性。

将这些部分放在一起,您可以执行以下操作:

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

enum { ISV = 8, PROD = 30, BUFF = 100 };    /* constants */

int main (int argc, char **argv) {

    char buff[BUFF] = "", prod[PROD] = "", id[ISV] = "", 
        stock[ISV] = "", vendas[ISV] = "", *delim = ":\n";
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed.\n");
        return 1;
    }

    while (fgets (buff, sizeof buff, fp)) { /* for each line of input */
        int i = 0, n = 0;   /* tokenize buff into words */
        for (char *p = strtok (buff, delim); p; p = strtok (NULL, delim)) {
            switch (i) {
                case 0: strncpy (id, p, ISV);       /* handle id */
                        if (strlen (p) >= ISV)
                            id[ISV-1] = 0;
                            i++;
                        break;
                case 1: strncpy (prod, p, PROD);    /* handle prod */
                        if (strlen (p) >= PROD)
                            prod[PROD-1] = 0;
                            i++;
                        break;
                case 2: strncpy (stock, p, ISV);    /* handle stock */
                        if (strlen (p) >= ISV)
                            stock[ISV-1] = 0;
                            i++;
                        break;
                case 3: strncpy (vendas, p, ISV);   /* handle vendas */
                        if (strlen (p) >= ISV)
                            vendas[ISV-1] = 0;
                            i++;
                        break;
                default: break;
            }
        }
        n++;

        printf ("id: %s,  prod: %s,  stock: %s,  vendas: %s\n",
                id, prod, stock, vendas);

        if (fp != stdin) fclose (fp);   /* close file */
    }
    return 0;
}

示例输入文件

$ cat dat/prod.txt
1000:Product1:0.75:5:0
1001:Product2:0.90:2:0
1002:Product3:0.55:8:0

示例使用/输出

$ ./bin/prod dat/prod.txt
id: 1000,  prod: Product1,  stock: 0.75,  vendas: 5
id: 1001,  prod: Product2,  stock: 0.90,  vendas: 2
id: 1002,  prod: Product3,  stock: 0.55,  vendas: 8

仔细看看,如果您有其他问题,请告诉我。