Sprawdzenie długości drugiego argumentu.

0

Witam piszę program, który pobiera z wiersza poleceń jeden znak i zero lub więcej nazw plików. I tutaj mam problem mianowicie nie wiem jak zrobić warunek, który zapewni mi to, że użytkownik jako drugi argument musi podać pojedynczy znak. Napisałem coś takiego, jednak przez to program mi wywala (twierdzę tak gdyż kiedy usunę te linijki program się uruchamia).

if ((strlen(argv[1])) != 1)
{
	puts("Drugim argumentem powinien byc pojedynczy znak");
	exit(1);
}

Jak można napisać taki warunek?

1

Wywalać się może tylko jeżeli nie będzie podanego drugiego argumentu. Jeżeli jest inaczej tzn. że nie ten kod powoduje error.

if (argc > 1 && strlen(argv[1]) != 1)
{
        puts("Drugim argumentem powinien byc pojedynczy znak");
        exit(1);
}
0

Mam jeszcze jedno pytanie i jest ono związane z poprzednim programem, więc nie będę zakładał nowego tematu. Oto kod programu:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX 41

int main(int argc, char *argv[])
{
	FILE *wsk;
	char nazwa[MAX];
	char ch;
	int ilosc = 0;
	int i = 2;

	if (argc > 1 && strlen(argv[1]) != 1)
	{
        puts("Drugim argumentem powinien byc pojedynczy znak");
        exit(1);
	}
	if (argc > 2)
	{
		while (i <= argc - 1)
		{
			if ((wsk = fopen(argv[i], "r")) == NULL)
			{
				puts("Blad otwarcia pliku");
				exit(1);
			}
			while (ch = getc(wsk) != EOF)
			{
				if (ch == *argv[1])
					ilosc++;
			}
			if (fclose(wsk) != 0)
			{
				puts("Blad zamkniecia pliku");
				exit(1);
			}
			printf("%s %s %d\n", argv[i], argv[1], ilosc);
			ilosc = 0;
			i++;
		}
	}
	else if (argc == 2)
	{
		puts("Podaj nazwe pliku do otwarcia");
		while(gets(nazwa) != NULL && nazwa[0] != '\0')
		{
			if ((wsk = fopen(nazwa, "r")) == NULL)
			{
				puts("Blad otwarcia pliku");
				exit(1);
			}
			while (ch = getc(wsk) != EOF)
			{
				if (ch == *argv[1])
					ilosc++;
			}
			if (fclose(wsk) != 0)
			{
				puts("Blad zamkniecia pliku");
				exit(1);
			}
			printf("%s %s %d\n", nazwa, argv[1], ilosc);
			ilosc = 0;
			puts("Podaj nazwe pliku do otwarcia");
		}
	}
	getchar();
	getchar();
	return 0;
}

Program ma za zadanie pobierać z wiersza poleceń znak oraz nazwy plików do przeszukania. Jeśli użytkownik nie poda żadnej nazwy pliku to wtedy program prosi go o podanie nazwy pliku. Program przegląda pliki i zlicza ilość wystąpień tegoż znaku. I właśnie mam problem z tym zliczaniem. Wynikiem uruchomienia powyższego programu i wprowadzenia kilku nazw plików zawsze jest ilość = 0. I tutaj moje pytanie jak porównać znak występujący w pliku z drugim argumentem z wiersza poleceń (tym poszukiwanym znakiem). Błąd pewnie jest w tym fragmencie:

while (ch = getc(wsk) != EOF)
{
	if (ch == *argv[1])
	ilosc++;
}

Wiem, że w argv[] są przechowywane całe łańcuchy, a ja przyrównuje ten łańcuch z pojedynczym znakiem. Nie mam jednak bardzo pojęcia jakie zmiany wprowadzić aby wszystko było porównywane poprawnie.

0
olek1 napisał(a)
while (ch = getc(wsk) != EOF)
{
	if (ch == *argv[1])
	ilosc++;
}

Wiem, że w argv[] są przechowywane całe łańcuchy, a ja przyrównuje ten łańcuch z pojedynczym znakiem. Nie mam jednak bardzo pojęcia jakie zmiany wprowadzić aby wszystko było porównywane poprawnie.

Nie chce mi się czytać całego kodu programu, więc ograniczę się do powyższego listingu. Nie możesz porównać char do char*. Pamiętaj, że argv[1] jest tablicą znaków:

if ( ch == argv[1][0] )

Nawet jeśli w linii komend podasz jeden znak 'A' jako argument, zostanie on przechowany w (teoretycznie) dwuelementowej tablicy {'A', '\0'}.

#include <stdio.h>


int main(int  argc, const char  *argv[]) {
        printf("%c\n", argv[1][0]);
	printf("%s\n", argv[1][0] == 'A' ? "TRUE" : "FALSE");
        return 0;
}

Wynik:

beorn@nika /tmp $ ./test Ala
A
TRUE
beorn@nika /tmp $ ./test A
A
TRUE
beorn@nika /tmp $ ./test Kot
K
FALSE
0
Kumashiro napisał(a)

Nie chce mi się czytać całego kodu programu, więc ograniczę się do powyższego listingu. Nie możesz porównać char do char*. Pamiętaj, że argv[1] jest tablicą znaków:

No tak, właśnie zdaję sobie z tego sprawę. Tylko nie mam pojęcia co zrobić. Jeśli poszukiwany znak musi zostać podany przez wiersz poleceń i automatycznie staje się on tablicą znaków to jak to potem porównać z zawartością plików tekstowych, z których muszę odczytywać pojedyncze znaki.

0
olek1 napisał(a)

Tylko nie mam pojęcia co zrobić. Jeśli poszukiwany znak musi zostać podany przez wiersz poleceń i automatycznie staje się on tablicą znaków to jak to potem porównać z zawartością plików tekstowych, z których muszę odczytywać pojedyncze znaki.

Dziwne. Wydawało mi się, że Ci wyjaśniłem jak to zrobić, a nawet sypnąłem przykładami...

0
Kumashiro napisał(a)
olek1 napisał(a)

Tylko nie mam pojęcia co zrobić. Jeśli poszukiwany znak musi zostać podany przez wiersz poleceń i automatycznie staje się on tablicą znaków to jak to potem porównać z zawartością plików tekstowych, z których muszę odczytywać pojedyncze znaki.

Dziwne. Wydawało mi się, że Ci wyjaśniłem jak to zrobić, a nawet sypnąłem przykładami...

Tak, ale wychodziło na to samo. Przecież argv[1][0] == *argv[1] i nie tutaj leżał problem. Po prostu było za mało nawiasów w warunku pętli while.

1

OK. Spróbuj wrzucić powtarzający się kod do funkcji. Przy dużych plikach możesz też zyskać wczytując większe porcje danych i skanować na pamięci, np:

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


size_t  scan_buf(char  *buf, size_t  bufsize, char  chr) {
    size_t          cnt = 0, pos = 0;


    while ( pos <= bufsize ) {
        if ( buf[pos] == chr )
            cnt++;
        pos++;
    };

    return cnt;
}



int main(int  argc, const char  *argv[]) {
    size_t          cnt = 0, bytes_read;
    int             fd;
    char            buf[1024];


    if ( (argc == 1) || (argc > 3) ) {
        fprintf(stderr, "Usage:  chrcnt CHAR [FILE]\n");
        return 1;
    } else if ( argc == 2 ) {
        fd = 0;
    } else if ( (fd = open(argv[2], O_RDONLY)) == -1 ) {
        perror("open()");
        return 2;
    };

    do {
        bytes_read = read(fd, buf, sizeof(buf));
        cnt += scan_buf(buf, bytes_read, argv[1][0]);
    } while ( bytes_read > 0 );

    if ( fd )
        close(fd);

    fprintf(stdout, "Char `%c' was found %li times\n", argv[1][0], cnt);
    return 0;
}

(przy braku nazwy pliku nie pytam usera tylko czytam z stdin, bo łatwiej mi było testować)

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