Sprawdzenie długości drugiego argumentu.

Odpowiedz Nowy wątek
2011-07-29 13:27
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?

Pozostało 580 znaków

2011-07-29 13:50
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);
}

edytowany 1x, ostatnio: byku_guzio, 2011-07-29 13:51

Pozostało 580 znaków

2011-07-29 14:17
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.

Pozostało 580 znaków

2011-07-29 14:36
Kumashiro
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:

[email protected] /tmp $ ./test Ala
A
TRUE
[email protected] /tmp $ ./test A
A
TRUE
[email protected] /tmp $ ./test Kot
K
FALSE

Pozostało 580 znaków

2011-07-29 17:46
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.

Dobra poradziłem sobie już z tym. Powód był naprawdę idiotyczny... - olek1 2011-07-29 18:28

Pozostało 580 znaków

2011-07-29 18:54
Kumashiro
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...

Pozostało 580 znaków

2011-07-29 19:28
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.

Pozostało 580 znaków

2011-07-29 20:54
Kumashiro
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ć)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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