Zadanie string ANSI C

0

Kolejne zadanko z serii ANSI C

**Użytkownik wprowadza pewien napis (linię znaków) składającą się z jednostek rozdzielonych przecinkiem (,) lub średnikiem (;). Niektóre z tych jednostek są liczbami całkowitymi. Napisz program, który odczyta wprowadzoną linię, znajdzie w niej liczby całkowite i wypisze ich liczbę oraz średnią arytmetyczną (średnia oczywiście nie musi być liczbą całkowitą).

W rozwiązaniu wykorzystaj funkcje z bibliteki string i funkcję atoi. Zwróć uwagę na elegancję i zwięzłość kodu.**

Mój problem, napisałem kod działa dla większości przypadków np:
33, 7go, 22, abc

lub

33; asc ; 67, d7,0

**ale problem pojawia się tu: **
np. gdy wprowadzę samą spację, albo np " - 5" minus spacja liczba, a program musi tolerować spację przed liczbą albo minus

Poniżej wstawiam swój kod:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int sprawdz(char schowek[])
{
    unsigned long i;
    int j;
    
    i=strlen(schowek);
   
    j=0;
    
    while(j<i)
    {
       
        if((schowek[j]>'9')&&(schowek[j]!='-')&&(schowek[j]!=' '))
           {
            return 1;
            }
         
        j++;
    }

           
           return 2;
}

int main()
{
    
    char napis[1000];
    char * schowek;
    int liczba;
    float srednia;

    int licznik = 0;
    float suma = 0;
    char korektor[3] = ",;";
    
    gets(napis);
    
    schowek = strtok(napis, korektor);
   
    while( schowek != NULL)
    {
        if(sprawdz(schowek)==2)
        {
            liczba=atoi(schowek);
        
            
            licznik++;
            suma +=liczba;
        
        }
            schowek = strtok(NULL, korektor);
   
        }
    
    
    
    if(licznik!=0)
    {
    srednia = suma/ licznik;
     printf("\nŚrednia :%.2f\nIlość liczb całkowitych: %d \n", srednia, licznik);
    }
    else
    {
        printf("Brak liczb całkowitych \n");
    }
   
    
    
    return 0;
}

2

Czy zadanie to jasno określa, że muszą być wspierane spacje między minusem a liczbą? Bo to dość niespotykane jest.

0

Nie muszą, ale chodzi o to, że mój program jak jest coś takiego to wypisuje że jest jedna liczba całkowita i średnia zero. A muszę tolerować minusy i spacje bo może być taka liczba " 5"

1

zamiast char korektor[3] = ",;"; daj po prostu char korektor[] = ",;";. Kompilator będzie wiedział, że na końcu jest '\0' i stworzy odpowiednio dużą tablicę. Jak dasz mniej to może być kiszka.

atoi przy niepowodzeniu zwraca 0 więc może to być niedostatecznym testem w przypadku gdy między minusem a liczbą jest spacja, wtedy przesuń minus do pierwszego niebiałego znaku i zrób atoi jeszcze raz dla pierwszego atoi, który zwrócił zero.

1

tak, dlatego muszę napisać tak program żeby przy użyciu funkcji ze standardowej biblioteki i biblioteki string.h + funkcji atoi tak żeby dobrze rozpoznało co jest faktycznie liczą a co nie i ja mam taki problem że to rozpoznaje prawie dobrze bo jest taki problem że moja funkcja sprawdź przepuszcza spacje minusa i cyfry dlatego jak słowo składa się ze spacji i minusa to jest liczone przez licznik jako liczba a atoi zwraca poprawnie zero ale to psuje mi srednia bo dziele przez więcej liczb

No to ty potrzebujesz jakiegoś regex-a zaimplementować, żeby stwierdzić czy dany napis pasuje do wzorca liczby całkowitej.

Analizować można też w kilku etapach:

  1. zaimplementować pomocniczą funkcję trim, czyli pozbycie się na początku i na końcu białych znaków
  2. sprawdzenie czy pierwszy znak to minus.
  • true: od drugiego znaku do końca musimy stwierdzić czy wszystki znaki to cyfry
  • false: od pierwszego znaku do końca spodziewamy się cyfr

Albo zbudować prostą maszynę stanów (FSM) z enum-em na switch-u, która przeanalizuje zawartość bufora i sprawdzi czy jest tam cyfra

Ps. Zamiast:

if((schowek[j]>'9')&&(schowek[j]!='-')&&(schowek[j]!=' '))

możesz skorzystać z gotowych funkcji

#include <ctype.h>
if( !isdigit(schowek[j]) && schowek[j] != '-' && !isspace(schowek[j]) )
1

Ja bym po prostu wstępnie przetworzył napis z liczbami i tekstem i usunął z niego wszystkie spacje i już. ;)

Wklejam kod ;)

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

void usunSpacje(char * str)
{
	char nowyStr[10000];
	int dlugosc = strlen(str);
	int i = 0, j = 0;
	
	for (; i < dlugosc; i++)
		if (!isspace(str[i]))
			nowyStr[j++] = str[i];
	
	nowyStr[j++] = '\0';
	
	for (i = 0; i < j; i++)
		str[i] = nowyStr[i];
}

int parsuj(char * str, int * num)
{
	char * element;
	char separator[] = ",;";
	int i = 0;
	
	element = strtok(str, separator);
	
	for (i = 0; element != NULL; i++)
	{
		num[i] = atoi(element);
		element = strtok(NULL, separator);
	}
	
	return i;
}

double sredniaLiczb(int * liczby, char * ciagBezSpacji, int n)
{
	double srednia = 0;
	int ilosc = n;
	int i = 0;
	char separator[] = ",;";
	char * element;
	
	element = strtok(ciagBezSpacji, separator);
	
	for (i = 0; i < n; i++)
	{
		if (liczby[i] != 0)
			srednia += liczby[i];
		
		else if (!strcmp(element, "0")) // ciagi takie same
			;
		
		else
			ilosc--;
		
		element = strtok(NULL, separator);
	}
	
	return srednia / ilosc;
}

int main()
{
	char napis[] = "1, 2, abc, - 5, ha ha, 4, 5, 5a, - 1, ad";
	char kopia[10000];
	int liczby[10000];
	int n = 0;
	
	strcpy(kopia, napis);
	n = parsuj(napis, liczby);
	usunSpacje(kopia);
	
	printf("%f\n", sredniaLiczb(liczby, kopia, n));
	
	return 0;
}
0

A więc tak: ta funkcja sobie poradziła z - 5 zwraca że nie ma liczb całkowitych, ale problem jest jeszcze np gdy wpisze samą spację lub sam minus to zwraca jedna liczba całkowita średnia zero

int sprawdz(char schowek[])
{
    unsigned long i;
    int j;
    int w,m;
    
    w = atoi(schowek);
    usunSpacje(schowek);
    m = atoi(schowek);
    
    if(w!=m)
    {
        return 1;
    }
    
    i=strlen(schowek);
   
    j=0;
    
    while(j<=i)
    {

        if((schowek[j]>'9')&&(schowek[j]!='-')&&(schowek[j]!=' '))
           {
            return 1;
            }
        if(schowek[j]=='-')
        {
            while(j<=i)
            {
                
                if(schowek[j]>'9')
                {
                    return 1;
                }
                
                j++;
            }
        }
        

        j++;
    }
           
           return 2;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1