如何从文件中获取字符串并存储在2D char数组中,并将该2D char数组与C中的字符串进行比较?

时间:2017-08-25 21:18:46

标签: c arrays string gcc multidimensional-array

我有一个文本文件,它有

的值(我通常将它们称为upc_values)
01080006210
69685932764
40000114485
40000114724
07410855329
72908100004
66484101000
04000049163
43701256600
99999909001
07726009493
78732510053
78732510063
78732510073
78732510093
02842010109
02842010132
78732510213
02410011035
73999911110


 char *UPC_val = "99999909001";
 char upcbuf[100][12];
 char buf[12];

 memset(buf,0,sizeof(buf));
 memset(upcbuf,0,sizeof(upcbuf));

当我尝试fgets时,我将其存储在2D缓冲区中。

 while ( fgets(buf, sizeof(buf), f) != NULL ) {
        strncpy(upcbuf[i], buf, 11);
        i++;
 }

我试图在缓冲区中打印数据。

 puts(upcbuf[0]);

upcbuf [0]将整个数据保持在连续流中,

0108000621069685932764400001144854000011472407410855329729081000046648410100004000049163437012566009999990900107726009493787325100537873251006378732510073787325100930284201010902842010132787325102130241001103573999911110

我希望将此upc值(11位数)与另一个字符串(11位数)进行比较。我用了,

 if(strncmp(UPC_Val,upcbuf[i],11) == 0)
 {
      //do stuff here
 }

它没有正常工作,我使用了strstr(),

 if(strstr(upcbuf[0],UPC_val) != NULL)
 {
     //do stuff here
 }

我完全不知道它在做什么,我正在做正确的比较吗? 怎么做,请帮忙吗?

提前致谢。

2 个答案:

答案 0 :(得分:3)

要读取一行11位数字和'\n'字符串,需要一个至少为13的数组来存储字符串。没有什么理由这么紧张。建议2倍预期最大尺寸

char upcbuf[100][12];  // large enough for 100 * (11 digits and a \0)
...
#define BUF_SIZE (13*2)
char buf[BUF_SIZE];
while (i < 100 && fgets(buf, sizeof buf, f) != NULL ) {

删掉潜在的拖尾'\n&#39;

  size_t len = strlen(buf);
  if (len && buf[len-1] == '\n') buf[--len] = '\0';

检查长度并以某种方式处理。

  if (len != 11) exit(EXIT_FAILURE);

保存/打印数据

    // strncpy(upcbuf[i], buf, 11);  // fails to insure a null character at the end
    strcpy(upcbuf[i], buf);
    i++;
    puts(upcbuf[i]);

比较字符串

    if(strcmp(UPC_Val,upcbuf[i]) == 0) { 
      // strings match
    }

答案 1 :(得分:3)

如果你在@ chux的回答之后仍然无法使逻辑工作,那么这里有一个简短的例子来实现他的建议,它将文件名作为第一个参数读取,并且可选地将upc作为第二个参数进行搜索(默认情况下,它会搜索"99999909001" [在这种情况下,您只需阅读stdin上的文件])。

请注意使用enum来定义行和列值的全局常量。 (如果您愿意,可以使用独立的#define ROW 128#define COL 32)如果您需要在代码中使用常量,请在顶部定义一次,因此如果需要更改,则只需一个方便的位置更改值,而不是必须选择代码,或执行全局搜索/替换来更改它们。

例如,您可以按如下方式将逻辑放在一起:

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

enum { COL = 32, ROW = 128 };   /* an enum is convenient for constants */

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

    char buf[COL] = "",             /* buffer to read each line    */
        upcbuf[ROW][COL] = { "" },  /* 2D array of ROW x COL chars */
        *upcval = argc > 2 ? argv[2] : "99999909001";
    size_t n = 0;   /* index/counter */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;    /* file */

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

    /* fill upcbuf (you could search at same time, but let's fill) */
    while (n < ROW && fgets (buf, COL, fp)) {
        size_t len = strlen (buf);          /* get length          */
        /* test last char '\n', overwrite w/nul-terminating char   */
        if (len && buf[len - 1] == '\n')
            buf[--len] = 0;
        strcpy (upcbuf[n++], buf);          /* copy to upcbuf      */
    }

    if (fp != stdin) fclose (fp);       /* close file if not stdin */

    /* step through upcbuf - search for upcval */
    for (size_t i = 0; i < n; i++)
        if (strcmp (upcbuf[i], upcval) == 0) {
            printf ("upcval: '%s' found at line '%zu'.\n", upcval, i + 1);
            return 0;
        }

    printf ("upcval: '%s' not found in file.\n", upcval);

    return 0;
}

示例使用/输出

$ ./bin/upcbuf dat/upcfile.txt
upcval: '99999909001' found at line '10'.

$ ./bin/upcbuf dat/upcfile.txt 01080006210
upcval: '01080006210' found at line '1'.

$ ./bin/upcbuf dat/upcfile.txt 02410011035
upcval: '02410011035' found at line '19'.

$ ./bin/upcbuf dat/upcfile.txt "not there!"
upcval: 'not there!' not found in file.

另请注意,如果您只是在搜索单个upc,那么您可以在单个循环中组合读取和搜索,但由于您经常将其作为单独的函数读取,然后对代码中的其他位置的数据进行操作,示例只是将文件中的所有upc值读入数组,然后在单独的循环中搜索数组。仔细看看,查看所有答案,如果您有任何其他问题,请告诉我们。

作为最后一点,你已经检查过最后一个字符是'\n',但如果不是,会发生什么?您应该检查长度是否为COL-1,表明该行中的其他字符仍未读取并处理错误(或者只读取并丢弃剩余的字符)。您可以使用类似于以下内容的附加内容执行此操作:

    /* test last char '\n', overwrite w/nul-terminating char   */
    if (len && buf[len - 1] == '\n')
        buf[--len] = 0;
    else if (len == COL - 1) {  /* if no '\n' & len == COL - 1 */
        fprintf (stderr, "error: line excces %d chars.\n", COL - 1);
        return 1;
    }

而且,您需要使用else if并检查COL - 1而不是简单地使用else,因为您可能正在阅读没有的文件在文件的最后一行之后的POSIX行尾(例如换行符)。 fgets正确读取最后一行,即使没有POSIX行结束,但'\n'中也没有buf。因此,即使没有POSIX行结束,该行也可以是有效行,并且只要读取的字符数(+ nul-terminatedating char)确实可以完成读取不等于你的缓冲区大小。