简体   繁体   中英

My function doesn't work and i don't understand why ..in C

I'm working on a problem that keeps the evidence of a shop stock, there is a this part where it is asked to get the code of the product, which I must get by reversing the name of the product.

For example:

name of the product : snack
codebar: kcans

And everytings works just fine until it gets to the line with strcpy .

The menu is not in english but the first one gets the input the second will show the output.

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


typedef struct Product
{
    char productName[30];
    char productCode[30];
    int price;
    int stock;
    int date[3];
}P;

char* reverse(char *name)
{
    char aux[30];
    int i,j;

    for(i = strlen(name) - 1, j = 0; i >= 0; i--,j++)
    {
        aux[j] = name[i];
    }
    aux[j] = '\0';

    return aux[30];
}


int nameValidation(char *name)
{
    int i;
    for(i = 0; i < strlen(name); i++)
    {
        if(name[i] >= 'a' && name[i] <= 'z');
        else
        {
            return 0;
            break;
        }
    }
    if(i == strlen(name))
    return 1;
}

void input(P *product, int *n)
{
    (*n)++;
    do
    {
        printf("Product name: ");
        scanf("%s", (product + *n)->productName);

    } while (!nameValidation((product + *n)->productName));


    printf("Price: ");
    scanf("%d", &(product + *n)->price);

    printf("Quantity: ");
    scanf("%d", &(product + *n)->sotck);


    do
    {
        printf("Expiration day: ");
        scanf("%d", &(product + *n)->date[0]);

        if((product + *n)->date[0] >= 1 && (product + *n)->date[0] <= 30)
            break;
    } while (1);
   
    
    do
    {
        printf("Expiration month: ");
        scanf("%d", &(product + *n)->date[1]);

        if((product + *n)->date[1] >= 1 && (product + *n)->date[1] <= 12)
            break;
    } while (1);
    

    (product + *n)->date[2] = 2024;
    printf("Expiration Year: %d\n", (product + *n)->date[2]);

    strcpy((product + *n)->productCode, reverse((product + *n)->productName));
    printf("Product Code: %5s\n", (product + *n)->productCode);

}


void output(P *product, int n)
{
    int i;
    for(i = 0; i <= n; i++)
    {
        printf("Product name: %10s ", (product + i)->productName);

        printf("Price: %5d ", (product + i)->price);

        printf("Stock:%5d\n", (product + i)->stock);
    }

}


int main()
{
    int option;
    int n;
    P product[100];

    n = -1;
    do
    {
        printf("\n0.Iesire\n");
        printf("1.Citirea unui produs de la tastatura\n");
        printf("2.Afisarea produselor citite\n");
        printf("3.Afisarea produselor cu un pret mai mic dat de utilizator\n");
        printf("4.Sa se afiseze toate produsele care au lungimea numelui egala cu un numar par\n");
        printf("5.Afisarea primului produs care este egal cu un nume dat de utilizator\n");
        printf("6.Sa se realizeze produsul cifrelor fiecarui numar de bucati al produselor, apoi sa se copieze fiecare produs intr-un vector si sa se afiseze vectorul.\n");
        printf("7.Copierea tuturor codurilor produselor intr-un vector de sir de caractere, apoi afisare vectorului\n");
        printf("8.Copierea pretului produselor intr-un vector apoi afisarea vectorului in ordine crescatoare\n");
        printf("9.Sa se transforme prima litera din codul produsului in litera mare daca aceasta este vocala.Nu se vor folosii functii predefinite in schimbarea literei\n");
        printf("10.Sa se afiseze forma binara a numarului de bucati ale produselor care au numarul de bucati mai mic decat 100 .\n");
        printf("11.Sa se afiseze toate produsele care urmeaza sa expire in urmatoarele 10 zile.Utilizator va preciza de la tastatura ziua si luna curenta.\n");
        printf("12.Sa se pun pe ultimul rand al unei matrici de caractere de ordin dat de numarul de produse, primul caracter din fieacre nume de produs,pe restul '.'\n");
        printf("13.Stabilirea unui nou pret pt toate produsele daca utilizatorul doreste.Astfel utilizator va stabili procentajul cu care se vor scumpi produsele.\n");
        printf("14.Sa se stearga un produs precizat de utilizator prin numele acestuia\n");
        printf("Introduceti o optiune: ");
        scanf("%d", &optiune);

        switch (option)
        {
        case 1:
            input(product, &n);
            break;
        case 2:
            output(product, n);
            break;
        case 3:
            
            break;
        case 4:
            /* code */
            break;
        case 5:
            /* code */
            break;
        case 6:
            /* code */
            break;
        case 7:
            /* code */
            break;
        case 8:
            /* code */
            break;
        case 9:
            /* code */
            break;
        case 10:
            /* code */
            break;
        case 11:
            /* code */
            break;
        case 12:
            /* code */
            break;
        case 13:
            /* code */
            break;
        case 14:
            /* code */
            break;
        case 0:
            exit(1);
            break;
        
        default:
            printf("Introduceti o optiune valida");
            break;
        }

    } while (option != 0);
    
    return 0;
}

You shouldn't waste time typing in 15 'prompts' and 15 case labels as if adding more code will get things working. I strongly suggest deleting that code (or commenting out those lines) and focus your attention on the tiny utility pieces that you need to build upon.

Here's a 'fixed' version of reverse() to get you going. PLEASE work incrementally, testing every tiny extra line of code added, every tiny change you make. Mountains don't grow from the top down...

char *reverse( char *str ) {
    for( int i = 0, j = strlen( str ) - 1; i <= j; i++, j-- ) {
        char tmp = str[i];
        str[i] = str[j];
        str[j] = tmp;
    }
    return str;
}

int main() {
    char *str[] = { "the fish", "goats are good" };

    printf( "%s", str[0] );
    printf( " == %s\n", reverse( str[0] ) );

    printf( "%s", str[1] );
    printf( " == %s\n", reverse( str[1] ) );

    return 0;
}

Output:

the fish == hsif eht
goats are good == doog era staog

EDIT:

Because of criticism leveled at this answer, I feel dutybound to add this note.

Because this function reverses the string "in place", you will need to adapt the following line of code:

strcpy( (product + *n)->productCode, reverse((product + *n)->productName) );

to

reverse( strcpy( (product + *n)->productCode, (product + *n)->productName) );

I'm posting this acknowledged "code dump" revision of the original code (with a sprinkling of comments) to demonstrate how the "big picture" sketch can coexist with incremental development. Please study this example from the entry point of main() to the exit() of case 0: . Note how shorter names 'clarify' what the code in functions does. When you are tempted to "copy/paste/adapt" some lines of code, ask yourself if the functionality could be better served by breaking out a separate function.

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

typedef struct Product {
    char name[30]; // meaningful but shorter name
    char code[30]; // meaningful but shorter name
    int price;
    int stock;
    int exp_yr, exp_mo, exp_dy; // no confusion
} P_t; // conventional to use "_t" with tokens 'typedef'd

// primative 'helper' functions
char *getString( char *prompt, char *to, int len ) {
    printf( "%s", prompt );
    fgets( to, len, stdin );
    to[ strlen(to) - 1 ] = '\0'; // get rid of '\n'
    return to;
}

int getInt( char *prompt ) {
    char buf[32];
    return atoi( getString( prompt, buf, sizeof buf ) );
}

char *reverse( char *str ) { // "in place" string reversal
    int lft = 0;
    int rgt = strlen( str ) - 1;

    for( ; lft <= rgt; lft++, rgt-- ) {
        char tmp = str[ lft ];
        str[ lft ] = str[ rgt ];
        str[ rgt ] = tmp;
    }
    return str;
}

int nameValid( char *str ) { // check for bad chars
    if( *str == '\0' ) return 0; // At least one char required

    char *permitted = "- abcdefghijklmnopqrstuvwxyz"; // extra acceptable chars

    return strspn( str, permitted ) == strlen( str ); // true if all chars okay
}

void input( P_t *pp ) { // fill-in ONE record
    do {
        getString( "Product name: ", pp->name, sizeof pp->name );
    } while( !nameValid( pp->name ) );

    reverse( strcpy( pp->code, pp->name ) );
    printf( "Product Code: %s\n", pp->code );

    pp->price = getInt( "Price: " );
    pp->stock = getInt( "In stock: " );

    // Not good, but sufficient
    while( ( pp->exp_dy = getInt( "Exp. day: " ) ) < 1 || pp->exp_dy > 31 ) {} // loop

    while( ( pp->exp_mo = getInt( "Exp. month: " ) ) < 1 || pp->exp_mo > 12 ) {} // loop

    pp->exp_yr = getInt( "Exp. year: " );
}

// Renamed to show outputs multiple records
// Equivalent, but easier to think of as array
void outputAll( P_t prod[], int n ) {

    for( int i = 0; i < n; i++ ) { // NB: changed '<=' to '<'
        P_t *pp = &prod[ i ]; // less verbose

        printf( "Product name: %10s ", pp->name );
        printf( "Price: %5d ", pp->price );
        printf( "Stock:%5d", pp->stock );
        printf( "\n" ); // Clearly 'end of line'
    }
}

int main() {
    P_t product[100]; // uninitialised
    int count = 0;

    memset( product, 0, sizeof product ); // Now initialised

    for( ;; ) {
        printf(
            "\n0.Iesire\n" );
        printf(
            "1.Citirea unui produs de la tastatura\n" );
        printf(
            "2.Afisarea produselor citite\n" );
/*      printf(
            "3.Afisarea produselor cu un pret mai mic dat de utilizator\n" );
        printf(
            "4.Sa se afiseze toate produsele care au lungimea numelui egala cu un numar par\n" );
        printf(
            "5.Afisarea primului produs care este egal cu un nume dat de utilizator\n" );
        printf(
            "6.Sa se realizeze produsul cifrelor fiecarui numar de bucati al produselor, "
            "apoi sa se copieze fiecare produs intr-un vector si sa se afiseze vectorul.\n" );
        printf(
            "7.Copierea tuturor codurilor produselor intr-un vector de sir de caractere, "
            "apoi afisare vectorului\n" );
        printf(
            "8.Copierea pretului produselor intr-un vector "
            "apoi afisarea vectorului in ordine crescatoare\n" );
        printf(
            "9.Sa se transforme prima litera din codul "
            "produsului in litera mare daca aceasta este vocala. "
            "Nu se vor folosii functii predefinite in schimbarea literei\n" );
        printf(
            "10.Sa se afiseze forma binara a numarului de bucati "
            "ale produselor care au numarul de bucati mai mic decat 100 .\n" );
        printf(
            "11.Sa se afiseze toate produsele care urmeaza sa expire in urmatoarele 10 zile. "
            "Utilizator va preciza de la tastatura ziua si luna curenta.\n" );
        printf(
            "12.Sa se pun pe ultimul rand al unei matrici de caractere de ordin "
            "dat de numarul de produse, primul caracter "
            "din fieacre nume de produs,pe restul '.'\n" );
        printf(
            "13.Stabilirea unui nou pret pt toate produsele daca utilizatorul "
            "doreste.Astfel utilizator va stabili procentajul cu "
             "care se vor scumpi produsele.\n" );
        printf(
            "14.Sa se stearga un produs precizat de utilizator prin numele acestuia\n" );
*/

        switch ( getInt( "Introduceti o optiune: " ) ) {
            case 0:
                exit( 1 ); // Would 'return 0' be better?
                break;

            case 1:
                // increment it here, instead of using pointer there.
                // pass only one element to be filled in.
                input( &product[ count++ ] );
                break;

            case 2:
                outputAll( product, count );
                break;

// ToDo:
//          case 3: break;
//          case 4: break;
//          case 5: break;
//          case 6: break;
//          case 7: break;
//          case 8: break;
//          case 9: break;
//          case 10: break;
//          case 11: break;
//          case 12: break;
//          case 13: break;
//          case 14: break;
// End ToDo

            default:
                printf("Introduceti o optiune valida");
                break;
        }
    }
    
    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