简体   繁体   中英

issues putting char pointers into 2d array of char pointers

I'd love some help here, driving me nuts.

Large file using strtok to split up my lines. I'm trying to separate the first part out, save it into my symbolTblChar[lblCnt]. What I can't seem to understand is why, after pulling from the file , my output becomes so weird

INPUT

    "SPACE \n LINE \n A1 \n A2"

Code

char* symbolTblChar[MAX_SYMBOLS][100];
int lblCnt = 0;
char line[LINE_SIZE];
char* chk;


    while(fgets(line, sizeof line, fp) != NULL) {                                   
            chk = (char*)strtok( line, delims );
            printf("Adding %s to symbol table", chk);
            *symbolTblChar[lblCnt]=chk + '\0';
            lblCnt++;
            int t;
            for(t = 0; t < lblCnt; t++)
                     printf("%s\n", *symbolTblChar[t]);                     
    }

Output:

    Adding SPACE to symbol table
    Adding LINE to symbol table
    LINE
    Adding A1 to symbol table
    A1
    A1
    Adding A2 to symbol table
    A2
    A2
    A2

You need to allocate and store characters. With your code you are storing pointer of character array line and it will get overwritten when you read subsequent lines.

You need to do something like

*symbolTblChar[lblCnt]= strdup(chk);

Also, not sure you need double char pointer as

char* symbolTblChar[MAX_SYMBOLS][100];

You can work with below which will store MAX_SYMBOLS number of strings.

char* symbolTblChar[MAX_SYMBOLS];

I think I understand what it is you are trying to do. In addition to Rohan's answer, you are also stumbling over the use of strtok . While it is somewhat a catch 22, since you are reading a string with symbols separated by newlines , you can still make strtok work. Understand though, when using strtok , your first call to strtok uses the pointer to the string as its first argument:

chk = strtok (line, delims);

while all subsequent calls to strtok use NULL as the first argument:

chk = strtok (NULL, delims);

What is nice about strtok is it was tailor-made for parsing an entire string in a for loop format. eg:

for (chk = strtok (line, delims); chk; chk = strtok (NULL, delims))

Putting that together, and cleaning up symbolTblChar[MAX_SYMBOLS] to simply be an array of pointers to char , rearranging your logic a bit, provides the following example. I guessed at what you would need for LINE_SIZE and what would work for MAX_SYMBOLS (adjust as required):

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

#define LINE_SIZE    128
#define MAX_SYMBOLS   32

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

    char *symbolTblChar[MAX_SYMBOLS] = {NULL};
    char line[LINE_SIZE] = {0};
    char *chk = NULL;
    char delims[] = " \n";
    int lblCnt = 0;
    int t = 0;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (fp != stdin && !fp) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    printf ("\nCollecting Symbols:\n");
    while (fgets (line, LINE_SIZE, fp)) 
    {                                   
        for (chk = strtok (line, delims); chk; chk = strtok (NULL, delims)) {
            printf ("  Adding %s to symbol table\n", chk);
            symbolTblChar[lblCnt] = strdup (chk);
            lblCnt++;

            /* check for MAX_SYMBOLS */
            if (lblCnt == MAX_SYMBOLS) {
                fprintf (stderr, "warining: MAX_SYMBOLS limit reached.\n");
                break;
            }
        }
    }

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

    /* output */
    printf ("\nSymbols:\n");
    for (t = 0; t < lblCnt; t++)
        printf("  %s\n", symbolTblChar[t]);

    /* free allocated memory */
    for (t = 0; t < lblCnt; t++)
        free (symbolTblChar[t]);

    return 0;
}

Output

Using your sample input provides:

$ printf "SPACE \n LINE \n A1 \n A2\n" | ./bin/symbltbl

Collecting Symbols:
  Adding SPACE to symbol table
  Adding LINE to symbol table
  Adding A1 to symbol table
  Adding A2 to symbol table

Symbols:
  SPACE
  LINE
  A1
  A2

Note: you can of course remove the Adding X ... intermediate print line when you are done with it. Now, even though it may not be apparent, you need to free the memory associate with each symbol added to symbolTblChar using strdup (which both allocates and copies its argument to a new memory location). You can see that taking place at the end of main .

If this isn't what you intended, let me know. After looking at the question and what you were doing, this seemed like your logical intent. Let me know if you have any questions.

File Input: note, you can also provide an input filename as the first argument to the program and the program will read from the file instead of stdin . For example, the input file:

$ cat symbols.txt
  SPACE
  LINE
  A1
  A2

Output Reading from File

$ /bin/symbltbl symbols.txt

Collecting Symbols:
  Adding SPACE to symbol table
  Adding LINE to symbol table
  Adding A1 to symbol table
  Adding A2 to symbol table

Symbols:
  SPACE
  LINE
  A1
  A2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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