Why is sscanf not reading anything - c

so i am trying to read strings using sscanf but it doesn't seem to read anything. I followed the tutrial and it looks very similar. I can't figuere out why it is not reading anything.
int main(){
int status =0;
int ret = 0;
int arg;
char *cmdLine = NULL;
char *cmd=NULL;
size_t n = 0;
char *line = NULL;
char *token =NULL;
while (getline(&line, &n, stdin) > 0){
//toekenize line
token = strtok(line,";");
//go thorugh and scan for cmds
while(token !=NULL){
// printf("token=%s\n", token);
cmdLine = token;
printf("%s\n", cmdLine);
//read the commands
ret=sscanf(cmdLine, "%31s %d", cmd, &arg);
printf("%d\n", ret);
token = strtok(NULL, ";");
}//while loop 2
//set line and n back to null and 0.
line = NULL;
n = 0;
}//while loop 1

Try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int status =0;
int ret = 0;
int arg;
char *cmdLine = NULL;
char cmd[100];
size_t n = 0;
char *line = NULL;
char *token =NULL;
if (getline(&line, &n, stdin) > 0)
{
//toekenize line
token = strtok(line,";");
//go thorugh and scan for cmds
if(token != NULL)
{
// printf("token=%s\n", token);
cmdLine = token;
printf(">>>> %s \n", cmdLine);
//read the commands
ret = sscanf(cmdLine, "%s %d", cmd, &arg);
printf(">>>> %d \n", ret);
token = strtok(NULL, ";");
}//while loop 2
//set line and n back to null and 0.
line = NULL;
n = 0;
}//while loop 1
printf("Result string: %s and Arg: %d \n", cmd, arg);
}

Related

How to print part of a tokenized string from a file in C

I am having some trouble with a tokenized string that is a line from a file. I want to print the line from where the token is found, but I cannot seem to find a way around it. Please, ignore the output to the file part as well as the author, class and method if statements as I have them sorted out.
For example, I want it to print from this line: #return the matric only this part: the matric
Code:
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv)
{
char line [1000];
char *delimeters = ".,; \t\n";
int total_lines = 0;
int total_comments = 0;
int nonblank_lines = 0;
FILE *input = fopen (argv[2], "r");
FILE *output = fopen (argv[4],"w");
while(fgets(line,1000,input) != NULL)
{
char *word = strtok(line, delimeters);
total_lines++;
if(word != NULL)
{
nonblank_lines++;
}
if(word != NULL && strcmp(word,"/**") == 0)
{
total_comments++;
}
while(word != NULL)
{
if(word != NULL && strcmp(word,"#author") == 0)
{
char *author_name = strtok(NULL, delimeters);
char *author_surname = strtok(NULL, delimeters);
printf ("Author: %s %s\n", author_name, author_surname);
}
if(word != NULL && strcmp(word,"public") == 0)
{
char *jmp = strtok(NULL, delimeters);
if(jmp != NULL && strcmp(jmp,"class") == 0)
{
char *class_name = strtok(NULL, delimeters);
printf ("Class %s\n", class_name);
}else{
char *method_name = strtok(NULL, delimeters);
printf ("Method %s\n", method_name);
}
}
if(word != NULL && strcmp(word,"#return") == 0)
{
printf("Enters IF 4\n");
char *return_value = strtok(NULL, delimeters);
printf ("Returns: %s\n", return_value;
}
/*if(word != NULL && strcmp(word,"#param") == 0)
{
printf("Enters IF 5\n");
char *parameters = strtok(NULL, delimeters);
printf("Parameter: %s\n", parameters);
//int param_found
}*/
word = strtok(NULL, delimeters);
}
}
printf ("The total number of lines is %d\n", total_lines);
printf ("The total number of non-blank lines is %d\n", nonblank_lines);
printf ("The total number of comments is %d\n", total_comments);
fclose(input);
fclose(output);
return 0;
}
So following my comment, you'd want something like this block for each if statement:
while(fgets(line, 1000, input) != NULL)
{
char *first_word_in_line = strtok(line, delimeters);
if(strcmp(first_word_in_line, "#return") == 0)
{
char *word = strtok(NULL, delimeters);
printf ("Returns: ");
while(word != NULL)
{
printf ("%s ", word);
word = strtok(NULL, delimeters);
}
printf("\n");
}
}
Note that I added another variable first_word_in_line on top word - it's not a must but it makes it less confusing when you code and it shows that the first word in the line has a different meaning because that's just the title.
Also, you should read about strcmp vs. strncmp. Usually it's a good practise to use strncmp.
The answer I got is this:
if(word != NULL && strcmp(word,"#return") == 0)
{
char *return_value = strtok(NULL, delimeters);
printf ("Returns: ");
while(return_value != NULL)
{
printf ("%s ", return_value);
return_value = strtok(NULL, delimeters);
}
printf("\n");
}
You messed a bit with the parameters at the beginning.
./program.c input.txt output.txt
argv[0] will give you the name of the program (in this case program.c), argv[1] the first param you pass (input.txt) and argv[2] the second parameter (output.txt)
There was also a missing bracket and for a comment /* comment */ one star in c is enough.
That fixed it worked for me.
But be aware if you cut the comment with strtok() the way you do it, there has to be a delimiter left and right to the start of your comment.
somecode; /* This should be recognized */
somecode;/* This not */
somecode; /*This neither */
Here ist the corrected code:
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv)
{
char line [1000];
char *delimeters = ".,; \t\n";
int total_lines = 0;
int total_comments = 0;
int nonblank_lines = 0;
FILE *input = fopen (argv[1], "r");
FILE *output = fopen (argv[2],"w");
while(fgets(line,1000,input) != NULL)
{
char *word = strtok(line, delimeters);
total_lines++;
if(word != NULL)
{
nonblank_lines++;
}
if(word != NULL && strcmp(word,"/*") == 0)
{
total_comments++;
}
while(word != NULL)
{
if(word != NULL && strcmp(word,"#author") == 0)
{
char *author_name = strtok(NULL, delimeters);
char *author_surname = strtok(NULL, delimeters);
printf ("Author: %s %s\n", author_name, author_surname);
}
if(word != NULL && strcmp(word,"public") == 0)
{
char *jmp = strtok(NULL, delimeters);
if(jmp != NULL && strcmp(jmp,"class") == 0)
{
char *class_name = strtok(NULL, delimeters);
printf ("Class %s\n", class_name);
}else{
char *method_name = strtok(NULL, delimeters);
printf ("Method %s\n", method_name);
}
}
if(word != NULL && strcmp(word,"#return") == 0)
{
printf("Enters IF 4\n");
char *return_value = strtok(NULL, delimeters);
printf ("Returns: %s\n", return_value);
}
/*if(word != NULL && strcmp(word,"#param") == 0)
{
printf("Enters IF 5\n");
char *parameters = strtok(NULL, delimeters);
printf("Parameter: %s\n", parameters);
//int param_found
}*/
word = strtok(NULL, delimeters);
}
}
printf ("The total number of lines is %d\n", total_lines);
printf ("The total number of non-blank lines is %d\n", nonblank_lines);
printf ("The total number of comments is %d\n", total_comments);
fclose(input);
fclose(output);
return 0;
}

Best way to read name value pair in c

What is the best way to read name and its value from a configuration file in c programming?
Sample configuration file:
NAME=xxxx
AGE=44
DOB=mmddyyyy
WORK=zzzz
This is the code which I am using. It is working. But I would like to know if there is a better way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getValue(char *line, char* name, char value[])
{
char* pch = NULL;
char* token = NULL;
pch = strstr(line, name);
if(pch)
{
token = strtok(pch, "=");
while (token != NULL)
{
pch = token;
token = strtok(NULL, "=");
}
pch[strcspn ( pch, "\n" )] = '\0';
strcpy(value,pch);
return 1;
}
return 0;
}
int main()
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
char value[100];
int ret = 0;
fp = fopen("test.txt", "r");
if (fp == NULL)
{
printf ("Cannot open file \n");
return -1;
}
while ((read = getline(&line, &len, fp)) != -1)
{
ret = getValue(line,"NAME",value);
if (ret)
{
printf("NAME is %s\n", value);
}
ret = getValue(line,"AGE",value);
if (ret)
{
printf("AGE is %s\n", value);
}
}
free(line);
fclose(fp);
return 0;
}
I would be also happy to hear if there is any issue with this code.
There are several issues
When the file is like below, your parsing is incorrect. it be found as long as there is this string on the line, regardless of whether it is on the value or part of the key.
NAMEX=xxxx
AGEX=44
DOB=mmddyyyyAGE
WORK=zzzzAGE
Use strtok line content will be changed. In fact, when you call getValue for the second time, the content of line is different from the file.
AGE=NAMEzzzz=1=2
From the performance, you can directly use line the substring, no need to strcpy out
It is recommended to parse the key and value first, then compare the key you are looking for multiple times. the code below is for reference only
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *trim(char *str)
{
char *start = str;
char *end = str + strlen(str);
while(*start && isspace(*start))
start++;
while(end > start && isspace(*(end - 1)))
end--;
*end = '\0';
return start;
}
int parse_line(char *line, char **key, char **value)
{
char *ptr = strchr(line, '=');
if (ptr == NULL)
return -1;
*ptr++ = '\0';
*key = trim(line);
*value = trim(ptr);
return 0;
}
int main()
{
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
char *key, *value;
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf ("Cannot open file \n");
return -1;
}
while ((read = getline(&line, &len, fp)) != -1) {
if (parse_line(line, &key, &value))
continue;
if (strcmp(key, "NAME") == 0) {
printf("NAME is %s\n", value);
} else if (strcmp(key, "AGE") == 0) {
printf("AGE is %s\n", value);
}
}
free(line);
fclose(fp);
return 0;
}

Declaring char array results segmentation fault in C programming language

I was just creating simple implementation where I read input.txt file which has one line of code containing two numbers separated by space (e.g. 4 4).
I was trying to separate them by delimiting with space first.
And I was trying to use the first value as a size of char array.
However it keeps causing segmentation fault but I have no idea.
int main(int argc, char **argv){
int number;
int i = 0;
char *token;
char buf[100];
int tempNum[2];
// Open file
FILE * fPointer;
fPointer = fopen("input.txt", "r");
// Read first line
fgets(buf, 1024, fPointer);
token = strtok(buf, " ");
number = atoi(token);
char charArray[number];
while(token != NULL){
tempNum[i] = atoi(token);
token = strtok(NULL, "\n");
printf("%d\n", tempNum[i]);
i++;
}
If I comment out "char charArray[number]" it does not cause segmentation fault. If I comment out only the while loop, it does not cause segmentation fault. But I cannot figure out why it is causing the segmentation in the first place. Please help.
Thank you in advance.
Something like this?
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
#define MAX_INPUT 2
int main(int argc, char **argv) {
char *token = NULL;
char *next_token = NULL;
char buf[BUF_SIZE];
long tempNum[MAX_INPUT] = { 0 };
const char *delim = " ";
char * end = NULL;
// Init vars
memset(buf, 0, BUF_SIZE);
// Open file
FILE * fPointer = fopen("input.txt", "r");
if (fPointer == NULL) {
return 1;
}
// Read first line
if (fgets(buf, BUF_SIZE, fPointer) == NULL) {
fclose(fPointer);
return 2;
}
// Parse line
token = strtok_s(buf, delim, &next_token);
for (int i = 0;((i < MAX_INPUT) && (token != NULL)); i++){
tempNum[i] = strtol(token, &end, 10);
if (*end != NULL){
printf("error in %s\n", token);
} else {
printf("%d\n", tempNum[i]);
}
token = strtok_s(NULL, delim, &next_token);
}
fclose(fPointer);
return 0;
}

while loop terminating before it is supposed to C

This program is supposed to copy an existing txt file to a new txt code file. However is isn't working right. For some reason it always stops after the third iteration.
Suggestions?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char fileNameIn[100];
char fileNameOut[100];
FILE *ptrIn = NULL; //____ File Pointers
FILE *ptrOut = NULL;
char str[1000]; //this is used at fgets and it obtains sentences
/*_________________Counter variables)*/
char *token;
int ctr = 0;
int ndel = -1;
char wordA[10];
char sentence[101];
char del[10] = " !-,.";
;
int temp = 0;
printf("Enter the input filename: \n");
// gets(fileNameIn);
scanf("%s", fileNameIn);
//printf("You entered: %s\n",fileNameIn);
printf("Enter the output filename: \n");
scanf("%s", fileNameOut);
ptrIn = fopen(fileNameIn, "r"); // r is to read
ptrOut = fopen(fileNameOut, "w"); //w is to write on file
if (ptrIn == NULL || ptrOut == NULL) {
printf("Unable to open file\n");
exit(1);
}
//while(fgets (str,sizeof(str), ptrIn) )
while (fgets(str, sizeof(str), ptrIn)) { // while we are not at the end of the file
puts(str);
// if(temp==0)
// {
token = strtok(str, del);
temp = -1;
printf(
"Enter position of word to delete (Start counting at 0). Enter -1 to skip deletion:\n");
scanf("%d", &ndel);
printf("You selected: %d\n", ndel);
while (token != NULL) // while loop inside a sentence
{
if (ctr != ndel) {
strcpy(wordA, token);
}
token = strtok(NULL, del);
if (ctr != ndel) {
strcat(sentence, wordA);
strcat(sentence, " ");
printf("halfway?");
}
ctr++;
} // endof sentence loop
fprintf(ptrOut, "%s", sentence);
printf("the sentence is now:\n%s", sentence);
printf("___________________________________________");
printf("\n");
strcpy(sentence, "");
ctr = 0;
ndel = -1;
} //end of while loop eof
printf("Finish the main: ");
fflush(ptrOut);
fclose(ptrIn);
fclose(ptrOut);
return EXIT_SUCCESS;
}
This is an example of the existing file:
test.txt:
hello my name is john.
this is a test.
after the third line the while
loop stops
this does the get copied
You strcat() to senetence wihtout initializing it, strcat() will search for the terminating nul byte of it's first argument and start copying characters from it's second argument start from that position, so a simple
sentence[0] = '\0';
right after the outer while loop will fix it, but your code needs reformatting and you should make it safer by checking every single potential undefined behavior cause.
This is the code and it now works correctly
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char fileNameIn[100] = {0};
char fileNameOut[100] = {0};
FILE *ptrIn = NULL;
FILE *ptrOut = NULL;
char str[1024] = {0};
char *token = NULL;
int ctr = 0;
int ndel = -1;
char wordA[1024] = {0};
char sentence[1024] = {0};
char del[] = " !-,.";
int temp = 0;
printf("Enter the input filename > ");
fflush(stdout);
scanf("%99s", fileNameIn);
printf("Enter the output filename > ");
fflush(stdout);
scanf("%99s", fileNameOut);
ptrIn = fopen(fileNameIn, "r"); // r is to read
if (ptrIn == NULL)
{
printf("Unable to open file %s\n", fileNameIn);
return -1;
}
ptrOut = fopen(fileNameOut, "w"); // w is to write on file
if (ptrOut == NULL)
{
fclose(ptrIn);
printf("Unable to open file %s\n", fileNameOut);
return -1;
}
while (fgets(str, sizeof(str), ptrIn)) // while we are not at the end of the file
{
puts(str);
token = strtok(str, del);
temp = -1;
printf("Enter position of word to delete (Start counting at 0) `-1 to skip deletion' > ");
if (scanf("%d", &ndel) != 1)
continue;
printf("You selected: %d\n", ndel);
sentence[0] = '\0';
while (token != NULL)
{
if (ctr != ndel)
strcpy(wordA, token);
token = strtok(NULL, del);
if (ctr != ndel)
{
strcat(sentence, wordA);
strcat(sentence, " ");
}
ctr++;
}
fprintf(ptrOut, "%s", sentence);
printf("the sentence is now:\n%s", sentence);
printf("\n");
ctr = 0;
ndel = -1;
}
printf("Finish the main: ");
fflush(ptrOut);
fclose(ptrIn);
fclose(ptrOut);
return EXIT_SUCCESS;
}

where is the pthread segfault happening?

in my program, I provide a directory which contains text files. Each of the text files contain a few hundred lines in the following format
Username,Password,BloodType,Domain,Number
I then create a thread for each file in the directory which will merge-sort(by number) these lines into the array char* text_lines[6000];
I can't figure out why I'm getting a segmentation fault because I'm getting different output on every run.
Heres my code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
void store_line(char* line);
void* my_merge_sort(void* file);
char** text_lines;
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: ./coolsort <directory>\n");
}
else
{
text_lines = malloc(6000 * sizeof(char*));
DIR* the_directory;
int filecount = 0;
struct dirent* directory_files[50];
if((the_directory = opendir(argv[1])) != NULL)
{
//make a list of the files in the directory
while((directory_files[filecount++] = readdir(the_directory))) ;
filecount--;
//<<<DEBUGGING INFO>
int i;
fprintf(stderr,"there are %i files in %s:\n", filecount, argv[1]);
for(i = 0; i < filecount; i++)
{
fprintf(stderr, "%s\n",directory_files[i]->d_name);
}
char cwd[512];
chdir(argv[1]);
getcwd(cwd, sizeof(cwd));
fprintf(stderr, "the CWD is: %s\n", cwd);
//<DEBUGGING INFO>>>
//lets start some threads
pthread_t threads[filecount-2];
int x = 0;
for(i = 0; i < (filecount); i++ )
{
if (!strcmp (directory_files[i]->d_name, "."))
continue;
if (!strcmp (directory_files[i]->d_name, ".."))
continue;
pthread_create(&threads[x++], NULL, my_merge_sort, (void*)directory_files[i]->d_name);
}
//do stuff here
//
}
else
{
fprintf(stderr, "Failed to open directory: %s\n", argv[1]);
}
}
}
void* my_merge_sort(void* file)
{
fprintf(stderr, "We got into the function!\n");
FILE* fp = fopen(file, "r");
char* buffer;
char* line;
char delim[2] = "\n";
int numbytes;
//minimize I/O's by reading the entire file into memory;
fseek(fp, 0L, SEEK_END);
numbytes = ftell(fp);
fseek(fp, 0L, SEEK_SET);
buffer = (char*)calloc(numbytes, sizeof(char));
fread(buffer, sizeof(char), numbytes, fp);
fclose(fp);
//now read the buffer by '\n' delimiters
line = strtok(buffer, delim);
fprintf(stderr, "Heres the while loop\n");
while(line != NULL)
{
store_line(line);
line = strtok(buffer, NULL);
}
free(buffer);
}
void store_line(char* line)
{
//extract the ID.no, which is the fifth comma-seperated-token.
char delim[] = ",";
char* buff;
int id;
int i;
strtok(line, delim);
for(i = 0; i < 3; i++)
{
strtok(line, NULL);
}
buff = strtok(line, NULL);
id = atoi(buff);
//copy the line to text_lines[id]
memcpy(text_lines[id], line, strlen(line));
}
edit: I checked to make sure that it would fit into the initial array, and found that the highest ID is only 3000;
You use of strtok() is wrong:
line = strtok(buffer, NULL);
should be
line = strtok(NULL, delim);
Another mistakes should be fixed similarly.
The elements of text_lines are uninitialized:
text_lines = malloc(6000 * sizeof(char*));
this allocated 6000 pointers to char, but none of these pointers are initialized.

Resources