Thread: Confused on fgets with switch

  1. #1
    Registered User
    Join Date
    Sep 2015
    Posts
    8

    Confused on fgets with switch

    Hi,

    I'm currently taking a class at my local college and the assignment is for me to retrieve data from a text file and count the number of 'a's, 'c's, 'g's, and 't's in the text file. When I run my code, it only counts the number of 'a's in the switch and I have no idea why. Could someone kindly look over my code and point out where I have erred? I have spent several hours trying to figure this out by myself, and really don't understand what I'm doing incorrectly !

    Code:
    /*
     ============================================================================
     Name        : xxx xxx xxx
     Author      : xxx xxx xxx
     Version     :
     Copyright   : Your copyright notice
     Description : Hello World in C, Ansi-style
     ============================================================================
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> /* required to run strcat, which adds text to the end of a string */
    #include <dirent.h> /* library for showing all files in a directory */
    
    
    int main(void) {
    	setvbuf(stdout, NULL, _IONBF, 0);
    
    
    unsigned int a=0,c=0,g=0,t=0;
    char filename[BUFSIZ],savename[BUFSIZ],stringCH[BUFSIZ];
    FILE *pInFile,*pOutFile;
    
    
    	/* LISTS ALL FILES IN DIRECTORY */
        DIR *d;
        struct dirent *dir;
        d = opendir(".");
        if (d)
        {
            printf("Here are the files in this directory:\n");
        	while ((dir = readdir(d)) != NULL)
            {
            	printf("%s\n", dir->d_name);
            }
            closedir(d);
        }
    
    
        /* INPUT READ FILE FROM USER */
    	printf("\nPlease type the name of a TEXT file to read from, without the extension:\n");
    	fgets(filename, BUFSIZ, stdin); /* user inputs file to load */
    	strtok(filename,"\n"); /* removes the \n from fgets */
    	strcat(filename,".txt"); /* adds .txt to the string */
    	if((pInFile=fopen(filename,"r"))==0)
    	{
    		printf("You entered %s which is invalid. You must enter a proper TEXT file! Goodbye!\n",filename);
    		fclose(pInFile);
    		exit(0);
    	}
    
    
    	/* INPUT WRITE FILE FROM USER */
    	printf("Excellent! Now create a name of a TEXT file to write to, without an extension:\n");
    	fgets(savename, BUFSIZ, stdin); /* user inputs file to load */
    	strtok(savename,"\n"); /* removes the \n from fgets */
    	strcat(savename,".txt"); /* adds .txt to the string */
    	pOutFile=fopen(savename,"w");
    
    
    	/* EXECUTION OF DATA RETREVIAL */
    	printf("Great! Retrieving data from the READ file:\n\n");
    	while(fgets(stringCH,BUFSIZ,pInFile)!=NULL)
    	{
    
    
    		switch(stringCH[1])
    		{
    		case 'a':
    			++a;
    			break;
    		case 'c':
    			++c;
    			break;
    		case 'g':
    			++g;
    			break;
    		case 't':
    			++t;
    			break;
    		default:
    			printf("There was no data to read from!");
    			break;
    		} //--> END OF SWITCH
    	} //--> END OF WHILE LOOP
    
    
    	if(feof(pInFile)) //--> AFTER END OF WHILE LOOP/CHECKS FOR END-OF-FILE TRUE
    	{
    		printf("Results are as follows:\n");
    		printf("A\tC\tG\tT\n");
    		printf("%d\t%d\t%d\t%d\t\n",a,c,g,t);
    		fprintf(pOutFile,"%d %d %d %d",a,c,g,t);
    		fclose(pInFile);
    		fclose(pOutFile);
    	}
    	else if(ferror(pInFile)) //--> IF ERROR READING FILE, GOODBYE!
    	{
    		printf("Error reading from file. Goodbye!\n");
    		fclose(pInFile);
    		fclose(pOutFile);
    		exit(0);
    	}
    
    
    return EXIT_SUCCESS;
    } //--> END OF MAIN

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Array indices start at zero, not one. Also, I don't see where you're declaring BUFSIZ.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Does each line only contain a couple characters? If not then you are only counting what is in the second position in your buffer for each line processed. Wouldn't you also need to loop through the entire line that you've just read (looping through the stringCH array) for each fgets call? What does the input data look like?
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  4. #4
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Quote Originally Posted by Elkvis View Post
    Array indices start at zero, not one. Also, I don't see where you're declaring BUFSIZ.
    Oh, I didn't realize that about arrays. According to my teacher, putting BUFSIZ in the buffer size makes the character size maximum, and from the code we've compiled in her class, it seems to work. I found this on a quick Google search:

    The GNU C Library: Controlling Buffering

    BUFSIZThe value of this macro is an integer constant expression that is good to use for the size argument to setvbuf. This value is guaranteed to be at least 256.
    The value of BUFSIZ is chosen on each system so as to make stream I/O efficient. So it is a good idea to use BUFSIZ as the size for the buffer when you callsetvbuf.
    Actually, you can get an even better value to use for the buffer size by means of the fstat system call: it is found in the st_blksize field of the file attributes. See Attribute Meanings.
    Sometimes people also use BUFSIZ as the allocation size of buffers used for related purposes, such as strings used to receive a line of input with fgets (seeCharacter Input). There is no particular reason to use BUFSIZ for this instead of any other integer, except that it might lead to doing I/O in chunks of an efficient size.

  5. #5
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Quote Originally Posted by hk_mp5kpdw View Post
    Does each line only contain a couple characters? If not then you are only counting what is in the second position in your buffer for each line processed. Wouldn't you also need to loop through the entire line that you've just read (looping through the stringCH array) for each fgets call? What does the input data look like?
    Each line has some random sentence I wrote in, and pasted several times. When fgets runs, it indeed takes the second latter, "a" in this case, and counts all of the 'a's on one line and outputs how many 'a's there are, which is 10 in this case, so the output for one line for the 'a's is correct.

    Re: looping through the entire line; yes indeed, that seems to be the issue I'm having, but I'm not sure what I'm doing wrong. Clearly, I am making a silly mistake or overlooking something simplistic here. This is the data from the data.txt file:

    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    data text is the new zebra world wide creationary art suspended in chlorine xenophobia yellow sun planet earth terrible fear anguish love
    I might add I'm confused on how to print multiple lines. This seems to only print the first line of the the text file, however I was under the impression fgets read to the end of the file.
    Last edited by taemex; 09-16-2015 at 02:49 PM.

  6. #6
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Okay, so I figured out that I was using an array and that's not what I want. So I changed my code based on some examples I found in my workbook and on StackOverflow, but it still does not work!?! Here is my current code (very similar), and what happens when I run it is it takes the read/write files correctly, but when the While loop runs, it just displays "There was no data to read from!" Clearly, the sscanf is outputting an integer when my switch requires a character. I just don't understand how to do this!?! It seems like it should be so simple, but I guess I'm C retarded at this point because I've read easily over fifty full examples at this point, and I still don't comprehend what I'm doing incorrectly . Here is my current code if anyone has any suggestions...

    Code:
    /*
     ============================================================================
     Name        : xxxxx.c
     Author      : xxxxx
     Version     :
     Copyright   : Your copyright notice
     Description : Hello World in C, Ansi-style
     ============================================================================
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> /* required to run strcat, which adds text to the end of a string */
    #include <dirent.h> /* library for showing all files in a directory */
    
    
    int main(void) {
        setvbuf(stdout, NULL, _IONBF, 0);
    
    
        unsigned int a = 0, c = 0, g = 0, t = 0;
        int stringCH;
        char filename[BUFSIZ], savename[BUFSIZ], lineCH[BUFSIZ+1];
        FILE *pInFile, *pOutFile;
    
    
        /* LISTS ALL FILES IN DIRECTORY */
        DIR *d;
        struct dirent *dir;
        d = opendir(".");
        if (d) {
            printf("Here are the files in this directory:\n");
            while ((dir = readdir(d)) != NULL) {
                printf("%s\n", dir->d_name);
            }
            closedir(d);
        }
    
    
        /* INPUT READ FILE FROM USER */
        printf(
                "\nPlease type the name of a TEXT file to read from, without the extension:\n");
        fgets(filename, BUFSIZ, stdin); /* user inputs file to load */
        strtok(filename, "\n"); /* removes the \n from fgets */
        strcat(filename, ".txt"); /* adds .txt to the string */
        if ((pInFile = fopen(filename, "r")) == 0) {
            printf(
                    "You entered %s which is invalid. You must enter a proper TEXT file! Goodbye!\n",
                    filename);
            fclose(pInFile);
            exit(0);
        }
    
    
        /* INPUT WRITE FILE FROM USER */
        printf(
                "Excellent! Now create a name of a TEXT file to write to, without an extension:\n");
        fgets(savename, BUFSIZ, stdin); /* user inputs file to load */
        strtok(savename, "\n"); /* removes the \n from fgets */
        strcat(savename, ".txt"); /* adds .txt to the string */
        pOutFile = fopen(savename, "w");
    
    
        /* EXECUTION OF DATA RETREVIAL */
        printf("Great! Retrieving data from the READ file:\n\n");
    
        /////////////////////PROBLEM IS HERE SOMEWHERE...////////////////////////
        while (fgets(lineCH, BUFSIZ, pInFile) != NULL) {
    
    
            sscanf(lineCH,"%1d",&stringCH);
            switch (stringCH) {
         /////////////////////PROBLEM IS HERE SOMEWHERE...////////////////////////
            case 'a':
                ++a;
                break;
            case 'c':
                ++c;
                break;
            case 'g':
                ++g;
                break;
            case 't':
                ++t;
                break;
            default:
                printf("There was no data to read from!\n");
                break;
            } //--> END OF SWITCH
        } //--> END OF WHILE LOOP
    
    
        if (feof(pInFile)) //--> AFTER END OF WHILE LOOP/CHECKS FOR END-OF-FILE TRUE
                {
            printf("Results are as follows:\n");
            printf("A\tC\tG\tT\n");
            printf("%d\t%d\t%d\t%d\t\n", a, c, g, t);
            fprintf(pOutFile, "%d %d %d %d", a, c, g, t);
            fclose(pInFile);
            fclose(pOutFile);
            fprintf(stdout,"Complete\n");
        } else if (ferror(pInFile)) //--> IF ERROR READING FILE, GOODBYE!
                {
            printf("Error reading from file. Goodbye!\n");
            fclose(pInFile);
            fclose(pOutFile);
            exit(0);
        }
    
    
        return EXIT_SUCCESS;
    } //--> END OF MAIN
    Last edited by taemex; 09-18-2015 at 10:19 PM.

  7. #7
    Registered User
    Join Date
    Feb 2012
    Posts
    347
    Can stringCH be of type char and sscanf format specifier be of type %1c instead of %1d?

  8. #8
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Quote Originally Posted by Satya View Post
    Can stringCH be of type char and sscanf format specifier be of type %1c instead of %1d?
    Satya, thank you for your reply,

    Changing %1d to %1c:

    warning: format '%c' expects argument of type 'char *', but argument 3 has type 'char (*)[512]
    Changing stringCH to type char:
    error: switch quantity not an integer
    Identical errors if only one changed or both.

    EDIT: Okay, I'm a moron, but I still haven't figured it out. fgets retrieves the entire string up to newline. My teacher said it only retrieved one character at a time. This is why switch won't work with whatever is in the while loop statement because switch needs a single character, not a string. Alright, so I'm almost there.... just have to figure out how to break down the string into single characters for the switch...

    EDIT-2: Here are the instructions for my assignment; I'm supposed to use fgets to retrieve one character at a time!!!...

    Functional Requirements

    Write a program that:

    1. Prompts the user for an input filename. The last character of this prompt must be a new line character (\n).
    2. Gets the input filename from stdin.
    3. Prompts the user for an output filename. The last character of this prompt must be a new line character (\n).
    4. Gets the filename from stdin.
    5. Opens the input file for reading.
    6. Opens the output file for writing.
    7. Reads nucleotide sequences from the input file.
      1. Do not prompt the user for the nucleotides, just use fgetc() to get each character.
      2. Each sequence consists of a series of A, C, G, or T characters, terminated by a \n.

    8. After each sequence is received, the number of A's, C's, G's, and T's are output on a single line to the file. Separate the number of A's, C's, G's, and T's by a single space.
    9. When an EOF is returned by fgetc(), the program closes the input and output files.
    10. Prints "Complete\n" to stdout.
    Last edited by taemex; 09-18-2015 at 11:29 PM.

  9. #9
    Registered User
    Join Date
    Sep 2014
    Posts
    364
    Biside that your attemp is wrong, it will only look at the first character of every line.
    But i assume that you want look at every character in every line.
    For this coal you should loop character by character over every line.
    Code:
    …
    int pos = 0;
    while (lineCH[pos]) {
        switch (lineCH[pos]) {
    …
        }
        pos++;
    }
    …
    Other have classes, we are class

  10. #10
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Incredible, that was it! Thank you so much WoodSTokk! Now all I have to figure out is how to get fgets to not stop after the first \n line, but to continue reading to eof and output the value of each line on a separate line. I suppose I'll need another while loop in there to accomplish this.

    EDIT: Holy god I think I just figured it out!!! Here I was bashing my brain trying to use fgets to get each character and NOT stop at the \n line, when the assignment is to use fgetc..... somebody kill me now....
    Last edited by taemex; 09-19-2015 at 01:00 AM.

  11. #11
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Okay, I figured it out completely if anyone is interested. I can't seem to edit old post after awhile it seems:
    Code:
    /*
     ============================================================================
     Name        : xxxxxx.c
     Author      : xxxxxx
     Version     :
     Copyright   : Your copyright notice
     Description : Hello World in C, Ansi-style
     ============================================================================
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> /* required to run strcat, which adds text to the end of a string */
    #include <dirent.h> /* library for showing all files in a directory */
    
    
    int main(void) {
    	setvbuf(stdout, NULL, _IONBF, 0);
    
    
    	unsigned int a = 0, c = 0, g = 0, t = 0;
    	int lineCH;
    	char filename[BUFSIZ], savename[BUFSIZ];
    	FILE *pInFile, *pOutFile;
    
    
    	/* LISTS ALL FILES IN DIRECTORY */
    	DIR *d;
    	struct dirent *dir;
    	d = opendir(".");
    	if (d) {
    		printf("Here are the files in this directory:\n");
    		while ((dir = readdir(d)) != NULL) {
    			printf("%s\n", dir->d_name);
    		}
    		closedir(d);
    	}
    
    
    	/* INPUT READ FILE FROM USER */
    	printf(
    			"\nPlease type the name of a TEXT file to read from, without the extension:\n");
    	fgets(filename, BUFSIZ, stdin); /* user inputs file to load */
    	strtok(filename, "\n"); /* removes the \n from fgets */
    	strcat(filename, ".txt"); /* adds .txt to the string */
    	if ((pInFile = fopen(filename, "r")) == 0) {
    		printf(
    				"You entered %s which is invalid. You must enter a proper TEXT file! Goodbye!\n",
    				filename);
    		fclose(pInFile);
    		exit(0);
    	}
    
    
    	/* INPUT WRITE FILE FROM USER */
    	printf(
    			"Excellent! Now create a name of a TEXT file to write to, without an extension:\n");
    	fgets(savename, BUFSIZ, stdin); /* user inputs file to load */
    	strtok(savename, "\n"); /* removes the \n from fgets */
    	strcat(savename, ".txt"); /* adds .txt to the string */
    	pOutFile = fopen(savename, "w");
    
    
    	/* EXECUTION OF DATA RETREVIAL */
    	printf("Great! Retrieving data from the READ file:\n\n");
    	printf("Results are as follows:\n");
    	printf("A\tC\tG\tT\n");
    
    
    	while (!feof(pInFile)) {
    		lineCH = fgetc(pInFile);
    
    
    		if (lineCH != '\n') {
    
    
    			switch (lineCH) {
    			case 'a':
    				++a;
    				break;
    			case 'c':
    				++c;
    				break;
    			case 'g':
    				++g;
    				break;
    			case 't':
    				++t;
    				break;
    			} //--> END OF SWITCH
    		} else if (lineCH == '\n') {
    			printf("%d\t%d\t%d\t%d\t\n", a, c, g, t);
    			fprintf(pOutFile, "%d %d %d %d\n", a, c, g, t);
    			a = 0, c = 0, g = 0, t = 0;
    		} //--> END OF IF-ELSE-IF
    	} //--> END OF WHILE LOOP
    
    
    	fprintf(stdout, "Complete\n");
    	fclose(pInFile);
    	fclose(pOutFile);
    	return EXIT_SUCCESS;
    } //--> END OF MAIN

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,776
    Are you supposed to count for each line, or count for the entire file?

    Don't do this:
    Code:
        while (!feof(pInFile)) {
            lineCH = fgetc(pInFile);
    Rather:
    Code:
        while ((lineCH = fgetc(pInFile)) != EOF) {
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Sep 2015
    Posts
    8
    Lol, I know, that's how I originally had it, but I wasn't sure if fgetc would reiterate correctly if it was in the while clause so I took it out and once the program worked as I wanted, I just left it that way, but I'll probably change it back now. Thanks!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fgets after scanf, skips over fgets?
    By willane1965 in forum C Programming
    Replies: 1
    Last Post: 08-17-2014, 11:13 PM
  2. Replies: 13
    Last Post: 07-06-2011, 07:48 PM
  3. fgets in switch-case problem
    By icestorm in forum C Programming
    Replies: 3
    Last Post: 08-20-2009, 07:07 PM
  4. confused (switch help)
    By zmaker5 in forum C Programming
    Replies: 9
    Last Post: 07-15-2007, 01:14 PM
  5. Confused about fgets, clearing the buffer, etc
    By caduardo21 in forum C Programming
    Replies: 1
    Last Post: 06-13-2005, 11:03 AM