简体   繁体   中英

C Program - Scanning in a String using scanf but reading from .txt file

I have an assignment to create a .txt file with the sentence

 "The quick brown fox jumps over the lazy dog." 

I named it pangram.txt and was instructed to scan it in after gcc -o ... by using:

myprogram_bin < pangram.txt

However, I am trying to find the number of occurrences of the letter 'e' and 'x' . My program returns the correct number for 'e' but returns 'x' 5 times. I have to have it return the statement "The character _ has been found." every time the character entered as input is found. I'm not sure if it's my loop or if I need to use something like const char *pangram to call my srting. Any help on how to correct my issue and have it scan in the file using standard input (cannot read in a file in my code), would be great!

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

void  problem_01_function(char char_to_find);

int main(){

    problem_01_function('e');
    problem_01_function('x');
    return 0;

}

void problem_01_function(char char_to_find){


    char pangram[50];
    scanf("%s", &pangram);
    int count_char_occur = 0;
    for(; count_char_occur < strlen(pangram);count_char_occur++)
    {
            if(pangram[count_char_occur] = char_to_find)
            {
                    printf("The character %c has been found. \n", char_to_find);
            }
    }
}

1) If you are going to scan the whole string

"The quick brown fox jumps over the lazy dog." 

with only 1 scanf()

then you do not have to use "%s" . You have to use other format:

scanf("%49[^.]", &pangram);

2) The comparison:

if(pangram[count_char_occur] = char_to_find)

should be

if(pangram[count_char_occur] == char_to_find)

3) You can use fscanf() instead of scanf() . this will avoid to call yoour program with < pangram.txt option

#include <stdio.h>

void  problem_01_function(char char_to_find);

int main(){
    problem_01_function('e');
    rewind(stdin);
    problem_01_function('x');
    return 0;
}

void problem_01_function(char char_to_find){
    int ch;
    while((ch = fgetc(stdin))!=EOF){
        if(ch == char_to_find)
            printf("The character %c has been found. \n", char_to_find);
    }
}

You can do it this way:

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

char * readme = "/Desktop/readme.txt";

void  problem_01_function(char char_to_find);

int main()
{
    problem_01_function('e');
    problem_01_function('x');
    return 0;
}

void problem_01_function(char char_to_find)
{
    int fd = 0 , count_char_occur = 0;
    char read_buff[50];
    fd = open(readme, O_RDONLY);
    read(fd, read_buff, 50);
    for(count_char_occur = 0; count_char_occur < strlen(read_buff); count_char_occur++)
    {
        if(read_buff[count_char_occur] = char_to_find)
        {
                printf("The character %c has been found. \n", char_to_find);
        }
    }
}

Edit - Sorry, I misread - if you're not allowed to read from a file, then modify the fgets line to read from stdin instead of pfile , and omit all fopen , fclose stuff.

void read_in_string_stdin (char pangram[]){
  printf("please enter the pangram\n");
  if (fgets(pangram, 50, stdin) == NULL) {
/* stuff */
}

and to compile and run:

gcc -Wall -o zpg pangram.c 
./zpg < pangram_file.txt 

For reading in from a file, you'll want to open a file using fopen , read with either fscanf or fgets , check the return value, and close the file with fclose .

  • If you use fscanf with the %s string, it will stop at the first whitespace encountered - hence use of the %[^.] or %[^\\n] formatting flags instead, to read until the first period or newline, respectively.

  • If you use fgets , it will read until a newline or a limiting number of characters have been read.

Also, you do have an assignment vs. equality-testing problem in the if loop.


Stylistically, there are also several issues (not error-producing on the computer's part, but error-prone for the reader) around the naming of variables and functions.

  • Name functions by what they do, not by metadata such as problem number.
  • The count_char_occur variable above is misleading, since it doesn't count occurrences of the sought char.
  • It's best to keep for -loop conditions as self-contained as possible, in case of later copy/paste (eg "I've pasted this elsewhere and ... what was the initial condition again??")

Here's a working and prettified version:

 void count_occurrences(char char_to_find) {
   /* Problem 01 function. */

   char pangram[50];
   FILE *pfile = fopen("pangram_file.txt", "r"); /* Opens in read-only mode. */                                                                               

   if (pfile == NULL) {
     printf("could not open file.  Exiting now.\n");
     exit(EXIT_FAILURE);
   }

   if (fgets(pangram, 50, pfile) == NULL) {
     printf("could not read string from  file.  Exiting now.\n");
     exit(EXIT_FAILURE);
   }
   fclose(pfile);
   printf("Now I have string |%s|\n", pangram);  /* Check that you have what you think */

   int string_pos; // "count_char_occur" was a misleading variable name
   int occurrences_found = 0;
   for (string_pos = 0; string_pos < strlen(pangram);string_pos++) { 
     if(pangram[string_pos] == char_to_find) { /* --- Assignment vs. Equality --- */
       printf("The character %c has been found, at position %i. \n", pangram[string_pos], string_pos);
       occurrences_found++;
     }
   }

/* Keep the user in the loop about what happened - reduce assumptions! */
   if (occurrences_found == 0)
     printf("The character %c was not found.\n\n", char_to_find);
   else
     printf("The character %c was found %i times in total.\n\n", char_to_find, occurrences_found);
 }

Now that you see this, this guy has a lot of responsibility, and it makes more sense to delegate one duty per function, doesn't it? Have one function handle the reading-in of the string, and another to count occurrences. Then you also aren't repeating the work of reading in the string for every different char you want to count in the same string.

void read_in_string (char pangram[]){        
  FILE *pfile = fopen("pangram_file.txt", "r");
  /* .... intervening lines as in above .... */
  printf("Now I have string |%s|\n", pangram);
}

void count_occurrences_only (char mystring[], char char_to_find) {
  int string_pos;
  /* .... intervening lines as in above, through end of count_occurrences .... */
}

int main(void) {
  char pangram[50];
  read_in_string(pangram);

  count_occurrences_only(pangram, 'e');
  count_occurrences_only(pangram, 'x');

  return 0;
}

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