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.