Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Weird Behavior in C For Loop

This program is designed to count how many vowels are in the words the user input, and the program ends when the user does CNTR+D. For some reason the last time the loop runs it always adds the last found vowel a second time.

 

So you would enter 'a' and it would say there were 2 of them.

 

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

int main(){
    
    // Creates string variable to store the users input
    char userString[64];

    // Prompts user for a string
    printf("Please enter a string that is all lowercase and less than 50 charecters\n");

    // Creates variables to store the number of each vowel in the string
    int numA = 0;
    int numE = 0;
    int numI = 0;
    int numO = 0;
    int numU = 0;

    // While loop to count how many of each vowel(s) are in the lowercase string
    while(1) {

        // Ends the program when the user enters CTRL+D
        if (feof(stdin)) break;

        // Stores the user input in userString
        scanf("%s", userString);

        for (int i = 0; userString[i] != '\0'; i++) {
            // Adds the 1 to the total number of each vowel when the vowel comes up in the string
            if (userString[i] == 'a') {
                numA += 1;
            }
            else if (userString[i] == 'e') {
                numE += 1;
            }
            else if (userString[i] == 'i') {
                numI += 1;
            }
            else if (userString[i] == 'o') {
                numO += 1;
            }
            else if (userString[i] == 'u') {
                numU += 1;
            }
        }
    }

    // Prints the output for the number of each vowel in the string
    printf("The vowel a occurred %d times\n", numA);
    printf("The vowel e occurred %d times\n", numE);
    printf("The vowel i occurred %d times\n", numI);
    printf("The vowel o occurred %d times\n", numO);
    printf("The vowel u occurred %d times\n", numU);

    // Returns a 0 to end the program
    return 0;
}

 

Link to post
Share on other sites
47 minutes ago, jrhaberland said:

This program is designed to count how many vowels are in the words the user input, and the program ends when the user does CNTR+D. For some reason the last time the loop runs it always adds the last found vowel a second time.

 

So you would enter 'a' and it would say there were 2 of them.

I'm not super well versed in some of the C stdio functions, but if you flip the positions of the ctrl-D check and parsing for text, it will return the correct values (per my simulations).

 

EDIT: Here's what I assume is happening in the loop...

  1. Ctrl-D is checked for
  2. String is parsed
  3. String is counted

However, by the time you can enter ctrl-D, the program is already blocking on the "string is parsed" line, so it has to loop through again before the ctrl-D check, and I assume that a ctrl-D input to the parse function doesn't fully overwrite what was in the buffer, so (most of?) it gets counted again. If you do it the other way around (as I suggest), you parse input, then check if it happens to be ctrl-D before continuing to count.

Main System (Byarlant): Ryzen 5 1600X | Asus B350-F Strix | Corsair H80i V2 | 16GB G.Skill DDR4 3200MHz CAS-14 | XFX RX 5600 XT THICC II | Samsung 960 PRO 512GB / Samsung 970 EVO 500GB / Seagate 7200RPM 3TB / WD White 7200RPM 8TB | Corsair CX650M | Mellanox ConnectX-2 10G NIC | Anidees AI-07BW Case | Dell U3415W Monitor | Microsoft Modern Keyboard

 

TrueNAS Server (Veda): Core i3-4170 | Supermicro X10SLL-F | Corsair H60 | 32GB Micron DDR3L ECC 1600MHz | 4x 10TB WD Whites / 1x Samsung PM961 128GB SSD / 1x Kingston 16GB SSD | Corsair CX430M | Mellanox ConnectX-2 10G NIC | LSI 9207-8i LBA | Fractal Design Node 804 Case (side panels swapped to show off drives)

 

Media Center/Video Capture (Jesta): Core i7-2600 | Asus H77M-PRO | Stock Cooler | 8GB No-name DDR3 | EVGA GTX750Ti SC | Sandisk UltraII SSD 64GB / Seagate 1.5TB HDD | Corsair CX450M | Hauppauge ImpactVCB-PCIe | Syba USB3.1 Gen 2 Card | LG UH12NS30 BD-ROM | Silverstone Sugo SG-11 Case

 

Laptop (Narrative): Lenovo Flex 5 81X20005US | Ryzen 5 4500U | 16GB RAM (soldered) | Vega 6 Graphics | SKHynix P31 1TB NVMe SSD | (all-around awesome machine)

Laptop (Rozen-ZuluSony VAIO VPCF13WFX | Core i7-740QM | 8GB Patriot DDR3 | GT 425M | Kingston 120GB SSD | Blu-ray Drive | (lived a good life, retired with honor)

 

Tablet (---): Samsung Galaxy Tab A 8" (crosses fingers)
Tablet (ReGZ)Asus T102HA (BIOS clock doesn't tick, loses time when sleep/off) (I kill tablets with disturbing regularity)

Tablet (Unicorn)Surface Pro 2 (battery will reset total capacity to current charge, leading Windows to think it's always 100% charged until it dies)

Tablet (Loto)Dell Venue 8 Pro (screen discoloration issues, wouldn't update to Windows 10)

Tablet: iPad 2 16GB (WiFi died, basically useless after that)

 

Testbed/Old Desktop (Kshatriya): Xeon X5470 @ 4.0GHz | ZALMAN CNPS9500 | Gigabyte EP45-UD3L | 8GB Nanya DDR2 400MHz | XFX HD6870 DD | OCZ Vertex 3 Max-IOPS 120GB | Corsair CX430M (?) | HooToo USB 3.0 PCIe Card | NZXT H230 Case

 

Camera: Sony ɑ7II (w/ Meike Grip) | Sony SEL24240 | Samyang 35mm ƒ/2.8 | Sony SEL50F18F | Sony SEL2870 (kit lens) | PNY Elite Perfomance SDXC cards

Link to post
Share on other sites
11 minutes ago, AbydosOne said:

However, by the time you can enter ctrl-D, the program is already on the "string is parsed" line, so it has to loop through again before the ctrl-D check,

Precisely this. At the beginning of loop #2, the EOF check fails, and scanf() gets called. scanf() encounters EOF, and returns without doing anything to userString. The loop continues, and parses userString again. At the beginning of loop #3, the EOF check passes, and the while loop breaks.

 

Instead of a while(true) loop, this should be the conditional check:

while(scanf("%s", userString) != EOF)

 

Link to post
Share on other sites

I was able to fix it by doing this

    // While loop to count how many of each vowel(s) are in the lowercase string
    while(1) {

        // Stores the user input in userString
        scanf("%s", userString);

        // Ends the program when the user enters CTRL+D
        if (feof(stdin)) {
            break;
        }

Essentially just had to switch it so the scanf is before the feof(stdin) statement.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×