简体   繁体   中英

why does the function skip the padding on the first call?

#include <iostream>
#include <cstring>
#include <cctype>

void go_lower(char *str);
void fill_str(char *mass);

int main()
{
    char str_1[80];
    char str_2[80];
    char *pointer_1;
    char *pointer_2;

    pointer_1 = str_1;
    pointer_2 = str_2;

    fill_str(pointer_1);

    fill_str(pointer_2);

    if(strcmp(str_1, str_2))
    {
        std::cout << "This strings are equal\n";
    }
    else
    {
        std::cout << "This strings are not equal\n";
    }


    return 0;
}

void fill_str(char *mass)
{
    std::cout << "Insert string to compare\n";
    while(*mass)
    {
        std::cin >> *mass;

        mass++;
    }
    std::cout << '\n';
}


void go_lower(char *str)
{
    while(*str)
    {
        if(isupper(*str))
        {
            *str = tolower(*str);
        }

        str++;
    }
}

Not so long ago I started studying programming and I try to understand the test tasks. In this program, I need to compare strings regardless of the case of the characters. when the program starts, it goes straight to filling in str_2 and the comparison block concludes that the strings are equal. What is the error?

The while (*mass) in your fill_str function will not loop even once because * mass may be initialized to 0 here (it is actually undefined behavior and up to your compiler). Because of this none of your strings will ever get filled with anything.

strcmp evaluates your strings equal because they are initialized in such a way they are equal from the beginning and are never changed because of the reason stated above.

To read a string consider using getline or std::cin if you know that your string will not contain spaces, eg.

std::cin >> mass;

See more here https://www.cplusplus.com/doc/tutorial/basic_io . Also consider using std::string instead of char arrays.

While in C++, you should really use std::basic_string , you still need to know how to handle plain-old-arrays. When passing an plain-old-array to a function to be filled, you must pass an additional parameter to provide the array size to the function. Within the function you can only read size - 2 characters into the array (saving index size - 1 for the nul-terminating character '\0' (ASCII 0 ).

You should also avoid using MagicNumbers in your code. Instead, if you need a constant (such as for 80 ), #define a constant or use a const int in C++. Since you have a choice for your return type, you should return the number of characters read into each string. The information will be available when you leave your fill_str() function and there is no reason to have to calling function re-scan for end-of-string.

You cannot use std::cin effectively to read multi-word input in a function as you are attempting. std::cin discards whitespace, so you will never read the '\n' generated by the user pressing [Enter] . So you have know way to know when the user is done typing. Instead you must use std::cin.get() ; which will read every character.

With those changes, you can write your function to use plain-old-arrays as follows:

#define MAXC 80     /* if you need a constant, #define one (or more) */
...
/* using plain-old-arrays, you must pass size of array */
size_t fill_str (char *mass, size_t size)
{
    size_t n = 0;   /* length counter */
    
    std::cout << "\nInsert string to compare\n";
    
    while (n < size - 1)                                /* read while array not full */
    {
        if ((*mass = std::cin.get()) && *mass != '\n')  /* use get() to read whitespace */
            n++;                    /* increment length counter */
        
        if (*mass == '\n')          /* if \n user pressed [Enter], input complete */
            break;
        
        mass++;                     /* increment pointer */
    }
    
    *mass = 0;                      /* nul-terminate when you leave read-loop */
    
    return n;                       /* return length */
}

Your example, omitting your unused go_lower() function, could then be:

#include <iostream>
#include <cstring>

#define MAXC 80     /* if you need a constant, #define one (or more) */

size_t fill_str (char *mass, size_t size);

int main (void)
{
    char str_1[MAXC];
    char str_2[MAXC];
    char *pointer_1;
    char *pointer_2;
    size_t len_1, len_2;

    pointer_1 = str_1;
    pointer_2 = str_2;

    len_1 = fill_str (pointer_1, MAXC);
    len_2 = fill_str (pointer_2, MAXC);
    
    if (len_1 != len_2) {
        std::cout << "\nstrings differ in length (" << 
                    len_1 << " != " << len_2 << ").\n";
        return 0;
    }
    
    if (strcmp (str_1, str_2) == 0)             /* only equal if return is 0 */
    {
        std::cout << "\nThis strings are equal\n";
    }
    else
    {
        std::cout << "\nThis strings are not equal\n";
    }

    return 0;
}

/* using plain-old-arrays, you must pass size of array */
size_t fill_str (char *mass, size_t size)
{
    size_t n = 0;   /* length counter */
    
    std::cout << "\nInsert string to compare\n";
    
    while (n < size - 1)                                /* read while array not full */
    {
        if ((*mass = std::cin.get()) && *mass != '\n')  /* use get() to read whitespace */
            n++;                    /* increment length counter */
        
        if (*mass == '\n')          /* if \n user pressed [Enter], input complete */
            break;
        
        mass++;                     /* increment pointer */
    }
    
    *mass = 0;                      /* nul-terminate when you leave read-loop */
    
    return n;                       /* return length */
}

Example Use/Output

$ ./bin/golower

Insert string to compare
apples and bananas

Insert string to compare
apples and bananas

This strings are equal

$ ./bin/golower

Insert string to compare
pickle

Insert string to compare
pickles

strings differ in length (6 != 7).

As mentioned at the beginning, you should really use std::string and getline() to read the user input, but you should also be familiar with plain-old-arrays. Look things over and let me know if you have questions.

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