1

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);
            }
    }
}
7
  • 4
    I think you mean to use == on this line: if(pangram[count_char_occur] = char_to_find) Commented Feb 14, 2014 at 15:59
  • need rewind(stdin); Commented Feb 14, 2014 at 16:12
  • Using re-directed input as in myprogram_bin < pangram.txt is not having the program read a .txt file. The program is still reading from stdin. The end effect of using < is similar for the first pass but code does not get to rewind stdin in general. Change code to read from a FILE* opened via fopen(pangram.txt,...). Commented Feb 14, 2014 at 16:29
  • You get the 'correct' answer for e by coincidence; the scanf() reads the word The and the faulty comparison counts each character in the string. The second call to scanf() reads quick and then counts 5 characters. You need to think about reading the whole line at once and scanning that. Either do this first and then scan the string for the character you're looking for, or rewind the file between letters. Generally, reading from a file is slow so you try to avoid reading a file more than once. Also note that you cannot usefully rewind standard input if the input is the terminal. Commented Feb 14, 2014 at 16:35
  • @chux: sorta...it is reading a text file; this standard input is seekable and rewindable, unlike terminal or pipe input. You're right that you often can't rewind standard input, but you can't rewind every file that you open, either (for example, /dev/tty is not rewindable either). Commented Feb 14, 2014 at 16:39

4 Answers 4

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

Parts 1 and 2 completely solved my problem! Since I have to use scanf for the assignment, part 3 does not apply since I cannot use fscanf. Thanks MOHAMED!
Instead of scanf, using fgets(stdin, pangram, sizeof pangram) is somewhat more elegant, and easier to maintain if you change the size of pangram, or if you end up opening a file with fopen anyway.
0
#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);
    }
}

5 Comments

Does rewind() do the same as what open(readme, O_RDONLY); read(fd, read_buff, 50); would do?
@WedaPashi File is passed to the program by a redirect.
Well, then it makes rewind() more efficient, doesn't it?
@WedaPashi I think that it does not change much.
stdin does not work if the console is not a redirect to a file, but the program does not work and in any case that.
0

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

Comments

0

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 (e.g. "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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.