while loop terminating before it is supposed to C - 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;
}

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;
}

How to give access to text file using if statement?

I am trying to give an if statement to check if a particular name is present in text file, then give access to it otherwise give error message.
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("For person details, please enter the person name: \n");
FILE * fr = fopen("/home/bilal/Documents/file.txt","r");
int catch, i=0, index=0;
char ch[100];
printf("Enter your Name: ");
if (scanf("%s", )){ // Don't know what to put here?
perror("Error while reading!");
return 0;
}
catch = fgetc(fr);
while(catch != EOF){
ch[index] = catch;
if (ch[index] == ' '){
ch[index] = '\0';
printf("Here is your result: %s\n",ch);
index = 0;
i++;
}
else
index++;
catch = fgetc(fr);
}
fclose(fr);
return 0;
}
Simply the program firstly opens a file and asks for a user input and verifies if the provided content is case-sensitively matched with the file. If so, then it'll let the program access the entire file and display on the screen, to do that, we must use another FILE b/c the old *fp is already manipulated and in case it's reused, it may display wrong data.
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fp = fopen("file.txt", "r"); // for verification
FILE *fp1 = fopen("file.txt", "r"); // for future use
char ch[50], str[50];
short int FLAG = 0;
printf("Enter the string: ");
scanf("%s", &str); // asks for input
while (fscanf(fp, "%s", ch) != EOF) {
if (!strcmp(ch, str)) { // checks if a string matches provided by the user
printf("Found! Here's your details...\n\n");
FLAG = 1;
}
}
if (!FLAG == 1) { // no? exits.
printf("Not found, access denied!\n");
return -1;
}
fclose(fp);
int c = fgetc(fp1); // yes? let's go...
while (c != EOF) {
printf("%c", c); // displays containing data
c = fgetc(fp1);
}
fclose(fp1);
return 0;
}
You'll want to add a variable for your scanf output:
char name[100];
if (scanf("%s", name) != -1)
// ...
Then to compare both you'll use strcmp.
#include <string.h>
//...
if (strcmp(ch, name) == 0)
// both are equal
Note that you can access documentation for scanf and strcmp by typing man scanf or man strcmp in your terminal.
int main()
{
printf("For person details, please enter the person name and id card
number: \n");
printf("Enter your Name: ");
char personName[100];
scanf("%s", personName);
printf("Enter your card number: ");
int cardNumber;
if (scanf("%d", &cardNumber)){
printf("no error detected");
}
else{
printf("error while reading");
}
return 0;
}
The fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
printf("For person details, please enter the person name: \n");
FILE* fr = fopen("/home/bilal/Documents/file.txt", "r");
int catch, i = 0, index = 0;
char ch[100] = { 0 };
if (fr == NULL)
{
perror("Invalid file opening!");
return 1;
}
printf("Enter your Name: ");
fgets(ch, 100, fr);
size_t len = strcspn(ch, "\n");
ch[(len < 100) ? (len) : (99)] = 0; // For file safety checking
if (strlen(ch)) { // Don't know what to put here?
perror("Error while reading!");
return 1;
}
catch = fgetc(fr);
while (catch != EOF) {
ch[index] = catch;
if (ch[index] == ' ') {
ch[index] = '\0';
printf("Here is your result: %s\n", ch);
index = 0;
memset(ch, 0, 100);
i++;
}
else
{
index++;
}
catch = fgetc(fr);
}
fclose(fr);
return 0;
}

Segmentation faulting in assignment

I'm currently learning C and I came from java. Our assignment asked us to count strings from either a file that could be added or it asks for the user to input a string. We just started using pointers and i looked up the different reasons why segmentation faults happened but I have no idea how to check for which issue it is. I initialized all my pointers to NULL but it still didn't work and from what i read that was the most common reason why a segmentation fault happens.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int debug = 0;
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
FILE* infile = NULL;
int c, err = 0;
int lflag = 0, sflag = 0, count = 0; //flags and count
char *shortWord = NULL, *longWord = NULL; //variable for shortest and longest word
int shortest = 100, longest = 0; //longest char 100, shortest 0
char *string = NULL;
char *pch = NULL;
static char usage[] = "usage: %s [-l] [-s] [filename]\n";
while ((c = getopt(argc, argv, "ls")) != -1)
switch (c)
{
case 'l':
lflag = 1;
break;
case 's':
sflag = 1;
break;
case '?':
err = 1;
break;
}
if (err)
{
fprintf(stderr, usage, argv[0]);
exit(1);
}
//checks for file and then runs loop for word count
infile = fopen("myfile.txt","r");
if (infile != NULL)
{
fgets(string, 100, infile);
pch = strtok (string, " ,.-");
while(pch != NULL)
{
count++;
if (strlen(pch) > longest)
longWord = pch;
if (strlen(pch) < shortest)
shortWord = pch;
pch = strtok (NULL, " ,.");
}
}
//else, asks for string
else
{
printf("Enter your string: \n");
fgets(string, 100, stdin);
int len = strlen(string);
count = len;
pch = strtok ( string, " ,.-");
while(pch != NULL)
{
count++;
if (strlen(pch) > longest)
longWord = pch;
if (strlen(pch) < shortest)
shortWord = pch;
pch = strtok (NULL, " ,.");
}
}
//following lines compute value based on arguments
if(lflag == 1)
{
printf("Longest word is %s", longWord);
}
if(sflag == 1)
{
printf("Shortest word is %s", shortWord);
}
printf("Word count = %.2d\n", count);
exit(0);
}
Their are some issues in your code:
You initialized string to NULL, then used it as an input buffer for fgets(). fgets() reqiures a pointer to an array of chars, either declared on the stack or dynamically allocated with malloc(3). You can set an input buffer such as char string[100].
fgets() must be checked, as it returns NULL when unable to read a line.
Your delimiter for strtok() is not accounting for the \n character appended by fgets(). You can either remove this newline, or include it in the delimter. If you want to include it in the delimeter, make sure your delimiter is " ,.-\n".
You could create function which parses your input with strtok(), as this would allow your main() to be shorter and reduce the repetitiveness in the code. An example function prototype could be void longest_shortest_words(char line[], char **longest, char **shortest, size_t *word_count);, whereby you pass the longest, shortest words along with the number of words back to main() via pointers. You could also just store the longest and shortest words in a 2D array or array of pointers.
You should also explicitly check that your file was opened correctly. Something like this should be included:
infile = fopen("myfile.txt", "r");
if (infile == NULL) {
fprintf(stderr, "Failed to open file\n");
exit(EXIT_FAILURE);
}
When checking opt, checking ? as a character in your switch statement is not right. Instead of:
case '?':
err = 1;
break;
Use default, which covers any other invalid option entered. Here is how you can use it:
default:
fprintf(stderr, "usage: %s [-l] [-s] [filename]\n", argv[0]);
exit(EXIT_FAILURE);
Checking sflag and lflag at the end is not enough. You should check if longWord and shortWord are not NULL.
Here is some example code which demonstrates these points:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LINESIZE 100
void longest_shortest_words(char line[], char **longest, char **shortest, size_t *wordcount);
void print_output(int lflag, int sflag, char *longword, char *shortword, size_t wordcount);
void remove_newline(char line[]);
int main(int argc, char * const argv[]) {
FILE *infile;
char line[LINESIZE] = {'\0'};
int opt, sflag = 0, lflag = 0;
size_t wordcount = 0;
const char *optstr = "ls";
char *longword = NULL, *shortword = NULL;
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch(opt) {
case 'l':
lflag = 1;
break;
case 's':
sflag = 1;
break;
default:
fprintf(stderr, "usage: %s [-l] [-s] [filename]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
/* Checking if file is in directory */
infile = fopen("myfile.txt", "r");
if (infile == NULL) {
fprintf(stderr, "Failed to open file\n");
exit(EXIT_FAILURE);
}
/* checking if line exists in file */
if (fgets(line, LINESIZE, infile) == NULL) {
fprintf(stderr, "No line found in file.\n");
printf("\nEnter string instead:\n");
if (fgets(line, LINESIZE, stdin) != NULL) {
remove_newline(line);
longest_shortest_words(line, &longword, &shortword, &wordcount);
/* checking that longWord, shortWord and word_count are valid */
if (longword != NULL && shortword != NULL && wordcount > 0) {
print_output(lflag, sflag, longword, shortword, wordcount);
}
}
/* file has line, do stuff with it */
} else {
remove_newline(line);
longest_shortest_words(line, &longword, &shortword, &wordcount);
print_output(lflag, sflag, longword, shortword, wordcount);
}
exit(EXIT_SUCCESS);
}
/* function for printing output, can be improved */
void print_output(int lflag, int sflag, char *longword, char *shortword, size_t wordcount) {
if (lflag) {
printf("Longest word: %s\n", longword);
}
if (sflag) {
printf("Shortest word: %s\n", shortword);
}
if (wordcount > 0) {
printf("Word count = %zu\n", wordcount);
}
}
/* function for removing newline, and checking that input hasnt exceeded limit */
void remove_newline(char line[]) {
size_t slen;
slen = strlen(line);
if (slen > 0 && line[slen-1] == '\n') {
line[slen-1] = '\0';
} else {
fprintf(stderr, "\nToo many characters in input.\n");
exit(EXIT_FAILURE);
}
}
/* function which parses line, and saves longWord and shortWord in pointers */
void longest_shortest_words(char line[], char **longword, char **shortword, size_t *wordcount) {
char *word = NULL;
const char *delim = " ,.";
word = strtok(line, delim);
if (word != NULL) {
*longword = word;
*shortword = word;
*wordcount = 1;
}
while ((word = strtok(NULL, delim)) != NULL) {
(*wordcount)++;
if (strlen(word) > strlen(*longword)) {
*longword = word;
} else if (strlen(word) < strlen(*shortword)) {
*shortword = word;
}
}
}
Note: The code shown above can be improved, it is just to show you another approach to your problem.

Why is sscanf not reading anything

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);
}

C programming, clearing a string

So I have some code that gets a user input and compares it in a loop, it will check the first line, then the second, then the third and so on, however the program doesn't get another clean string variable for the next cycle of the loop, as shown here:
char text[100], blank[100];
int c = 0, d = 0;
void space(void);
int main()
{
int loop=0;
char str[512];
char string[512];
int line=1;
int dis=1;
int score=0;
char text[64];
FILE *fd;
fd = fopen("Student Usernames.txt", "r"); //Should be test
if (fd == NULL)
{
printf("Failed to open file\n");
exit(1);
}
do
{
printf("Enter the string: ");
gets(text);
while (text[c] != '\0')
{
if (!(text[c] == ' ' && text[c] == ' ')) {
string[d] = text[c];
d++;
}
c++;
}
blank[d] = '\0';
printf("Text after removing blanks\n%s\n", string);
getch();
for(loop = 0;loop<line;++loop)
{
fgets(str, sizeof(str), fd);
}
printf("\nLine %d: %s\n", dis, str);
dis=dis+1;
str[strlen(str)-1] = '\0';
if(strcmp(string,str) == 0 )
{
printf("Match\n");
score=score+2;
}
else
{
printf("Nope\n");
score=score+1;
}
getch();
}
while(!feof(fd));
printf("Score: %d",score);
getch();
}
For example: Input: Apple (1st word) , 1st line = Apple, Match, Input: Banana, 2nd line = Applea
Clearly the program has added onto to first input, I want to know how to change this
Edit: Upon reseting c and d back to 0 after each loop the output is now "AppleBanana"

Resources