• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Łączenie tekstów (funkcje ze zmienną liczbą argumentów)

VPS Starter Arubacloud
0 głosów
379 wizyt
pytanie zadane 20 maja 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)
edycja 20 maja 2020 przez Hubertius

Cześć

Wykonuję obecnie takie oto zadanie:

apisz i przetestuj funkcję łączącą N tekstów do wspólnego bufora o następującym wywołaniu:

concatenate(res, 20, 3, "Ala", "ma", "kota");
Funkcja ma przyjmować w parametrze:

bufor tekstowy,
rozmiar bufora (pojemność),
liczbę tekstów oraz
kolejne teksty.
Wyjściem mają być teksty oddzielone spacjami.

W przypadku sukcesu funkcja powinna zwrócić wartość 0,
w przypadku błędnych danych wejściowych wartość 1,
a w przypadku, kiedy pojemność bufora jest za mała funkcja powinna zwrócić wartość 2.
Napisz program, który pobierze od użytkownika liczbę tekstów do wczytania (od 2 do 4), a następnie wczyta te teksty i wykorzystując przygotowaną wcześniej funkcję połączy je w jeden tekst.

Przygotuj tablicę dwuwymiarową, alokowaną dynamicznie, na teksty pobierane od użytkownika oraz tablicę jednowymiarową do przechowania wyniku połączonych tekstów.

Tablica dwuwymiarowa powinna umożliwić przechowanie maksymalnie 4 tekstów o długości 1000 znaków każdy. Natomiast tablica jednowymiarowa powinna pozwolić na zapis tych tekstów w formie połączonej spacjami.

W przypadku niepowodzenia alokacji pamięci program powinien wyświetlić komunikat Failed to allocate memory i zakończyć działanie z kodem błędu 8.
W przypadku wprowadzenia błędnych znaków program powinien wyświetlić komunikat Incorrect input i zakończyć działanie z kodem błędu 1.
W przypadku błędnych danych wejściowych komunikat Incorrect input data i zakończyć działanie z kodem błędu 2.
Przyjmij założenie, że długość tekstów nie przekroczy 1000 znaków. Jeżeli podany tekst będzie dłuższy, to pozostałe znaki powinny zostać zignorowane.

Program powinien wyświetlić wynik połączenia podanych tekstów w jeden tekst (w jednej linii, bez dodatkowych znaków).

Przykładowa interakcja z programem -- sukces:

Podaj liczbe tekstow do wprowadzenia: 3⏎
Podaj teksty: "The man who has confidence in himself gains the confidence of others."- Hasidic Proverb⏎
Teaching is a very noble profession that shapes the character, caliber, and future of an individual. If the people remember me as a good teacher, that will be the biggest honour for me. - A. P. J. Abdul Kalam⏎
A woman is like a tea bag; you never know how strong it is until it's in hot water. - Eleanor Roosevelt⏎
"The man who has confidence in himself gains the confidence of others."- Hasidic Proverb Teaching is a very noble profession that shapes the character, caliber, and future of an individual. If the people remember me as a good teacher, that will be the biggest honour for me. - A. P. J. Abdul Kalam A woman is like a tea bag; you never know how strong it is until it's in hot water. - Eleanor Roosevelt
Przykładowa interakcja z programem -- brak pamięci:

Limit sterty: 6038

Failed to allocate memory⏎
Przykładowa interakcja z programem -- błąd danych wejściowych:

Podaj liczbe tekstow do wprowadzenia: 6⏎
Incorrect input data
Podaj liczbe tekstow do wprowadzenia: KYtdkxB⏎
Incorrect input
Uwaga

W programie nie wolno używać operatora [].

Na tą chwilę tak rozpisałem mój kod:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
int concatenate(char * buffer, int size_of_buffer,int elements,...);
int main()
{
    printf("Podaj liczbe tekstow do wprowadzenia: ");
    int choice;
    if(scanf("%d",&choice)!=1)
    {
        printf("Incorrect input");
        return 1;
    }
    if( choice < 2 || choice > 4 )
    {
        printf("Incorrect input data");
        return 2;
    }
    int i = 0;
    char ** pointer = (char **) malloc(sizeof(char *) * choice);
    if( pointer == NULL )
    {
        printf("Failed to allocate memory");
        return 8;
    }
    for( i = 0; i < choice; i++)
    {
        *(pointer + i) = (char *) malloc(sizeof(char) * 2500);
        if( *(pointer + i) == NULL )
        {
            int get_out = 0;
            for(get_out = 0; get_out < i;get_out++)
            {
                free(*(pointer + get_out));
            }
            free(pointer);
        }
        scanf(" %2500[^\n]",*(pointer + i) );
        *(*(pointer + i) + 1000) = '\0';
    }


    return 0;
}

int concatenate(char * buffer, int size_of_buffer,int elements,...)
{
    if( buffer == NULL || elements <= 0 || size_of_buffer <= 0 )
    {
        return 1;
    }
    va_list list;
    va_start(list,elements);
    int compare = 0;
    char * point_on;
    int i = 0;
    for(i = 0; i < elements; i++)
    {
        point_on = va_arg(list,char *);
        compare += strlen(point_on);
    }
    compare += (elements - 1) + 1;  //na spacje i terminatora
    va_end(list);
    if( compare < buffer )
    {
        return 2;
    }
    
    return 0;
}

Zastanawiam się, czy to jak to rozpisałem (szczególnie w samej funkcji concatenate) jest na tą chwilę prawidłowe. Jeśli to jak teraz za pomocą zmiennej va_list mogę dokonać konkatenacji tychże tekstów?   :)

P.S Pomysł na dokończenie funkcji concatenate mam mniej więcej taki:

int concatenate(char * buffer, int size_of_buffer,int elements,...)
{
    if( buffer == NULL || elements <= 0 || size_of_buffer <= 0 )
    {
        return 1;
    }
    va_list list;
    va_start(list,elements);
    int compare = 0;
    char * point_on;
    int i = 0;
    for(i = 0; i < elements; i++)
    {
        point_on = va_arg(list,char *);
        compare += strlen(point_on);
    }
    compare += (elements - 1) + 1;  //na spacje i terminatora
    va_end(list);
    if( compare < size_of_buffer )
    {
        return 2;
    }
    va_start(list,elements);
    for(i = 0; i < elements; i++)
    {
        point_on = va_arg(list,char *);
        if( i == 0 )
        {
            strcpy(buffer,point_on);
        }
        if( i != 0 )
        {
            strcat(buffer,point_on);
        }
    }
    va_end(list);
    return 0;
}

 

1
komentarz 20 maja 2020 przez j23 Mędrzec (194,920 p.)
edycja 20 maja 2020 przez j23

Nie wstawiasz między słowa spacji.


Alternatywna wersja:

int concatenate(char* buffer, int size_of_buffer, int elements, ...)
{
    if (buffer == NULL || elements <= 0 || size_of_buffer <= 0) {
        return 1;
    }

    --size_of_buffer;

    va_list list;
    va_start(list, elements);

    while (elements--) {
        const char* p = va_arg(list, const char*);
        while (size_of_buffer && (*buffer = *p++)) { ++buffer; --size_of_buffer; }
        if (size_of_buffer == 0)
            return (*p || elements) ? 2 : 0;
        *buffer++ = ' '; 
        --size_of_buffer;
    }
    
    *--buffer = 0;
    
    va_end(list);
    return 0;
}

 

komentarz 20 maja 2020 przez Hubertius Bywalec (2,970 p.)

Ciekawe rozwiązanie. Ja swoje początkowe zmodyfikowałem i efekt ostateczny jest taki:



int concatenate(char * buffer, int size_of_buffer,int elements,...)
{
    if( buffer == NULL || elements <= 0 || size_of_buffer <= 0 )
    {
        return 1;
    }
    va_list list;
    va_start(list,elements);
    int length = 0;
    char * point_on;
    int i = 0;
    for(i = 0; i < elements; i++)
    {
        point_on = va_arg(list,char *);
        length += strlen(point_on);
        if( i == 0 )
        {
            strcpy(buffer,point_on);
            if( i != elements - 1)
            {
                strcat(buffer," ");
                length += 1;
            }
        }
        if( i != 0 )
        {
            strcat(buffer,point_on);
            if( i != elements - 1)
            {
                strcat(buffer," ");
                length += 1;
            }
        }
    }
    *(buffer + length ) = '\0';
    va_end(list);
    if( (length + 1) > size_of_buffer )
    {
        return 2;
    }
    return 0;
}

 

komentarz 20 maja 2020 przez Hubertius Bywalec (2,970 p.)

A nie wiesz może jak mógłbym zabezpieczyć swój program na wypadek takiego testu?

Podaj liczbe tekstow do wprowadzenia: 3⏎
Podaj teksty: This is why I loved technology: if you used it right, it could give you power and privacy.-Cory Doctorow⏎
⏎
Pain is temporary. Quitting lasts forever. - Lance Armstrong⏎

Problematyczny jest najwyraźniej ten

Tak wygląda mój kod:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
int concatenate(char * buffer, int size_of_buffer,int elements,...);
int main()
{

    char ** pointer = (char **) malloc(sizeof(char *) * 4);
    if( pointer == NULL )
    {
        printf("Failed to allocate memory");
        return 8;
    }
    char * buffer = (char *) malloc(sizeof(char) * (4 * 1000 + 3 + 1));
    if( buffer == NULL )
    {
        free(pointer);
        printf("Failed to allocate memory");
        return 8;
    }
    int i =0;
    for( i = 0; i < 4; i++)
    {
        *(pointer + i) = (char *) malloc(sizeof(char) * 1001);
        if( *(pointer + i) == NULL )
        {
            int get_out = 0;
            for(get_out = 0; get_out < i;get_out++)
            {
                free(*(pointer + get_out));
            }
            free(pointer);
            free(buffer);
            printf("Failed to allocate memory");
            return 8;
        }
    }
    int choice;
    printf("Podaj liczbe tekstow do wprowadzenia: ");
    if(scanf("%d",&choice) != 1 )
    {
        int get_out = 0;
        for(get_out = 0; get_out < 4;get_out++)
        {
          free(*(pointer + get_out));
        }
        free(pointer);
        free(buffer);
        printf("Incorrect input");
        return 1;
    }
    if( choice < 2 || choice > 4 )
    {
         int get_out = 0;
         for(get_out = 0; get_out < 4;get_out++)
         {
            free(*(pointer + get_out));
         }
         free(pointer);
         free(buffer);
         printf("Incorrect input data");
         return 2;
    }
    printf("Podaj teksty: ");
    for(i = 0; i < choice; i++)
    {
        scanf(" %1000[^\n]",*(pointer + i) );
        while( getchar() != '\n' );
    }
    if( choice == 2 )
    {
        concatenate(buffer,(choice * 1000 + (choice - 1) + 1),choice,*(pointer + 0) ,*(pointer + 1)  );
    }
    if( choice == 3 )
    {
        concatenate(buffer,(choice * 1000 + (choice - 1) + 1),choice,*(pointer + 0),*(pointer + 1), *(pointer + 2) );
    }
    if( choice == 4 )
    {
         concatenate(buffer,(choice * 1000 + (choice - 1) + 1),choice,*(pointer + 0),*(pointer + 1), *(pointer + 2) , *(pointer + 3) );
    }
    printf("%s",buffer);
    free(buffer);
    for(i = 0; i < 4; i++)
    {
        free( *(pointer + i));
    }
    free(pointer);
    return 0;
}

int concatenate(char * buffer, int size_of_buffer,int elements,...)
{
    if( buffer == NULL || elements <= 0 || size_of_buffer <= 0 )
    {
        return 1;
    }
    va_list list;
    va_start(list,elements);
    int length = 0;
    char * point_on;
    int i = 0;
    for(i = 0; i < elements; i++)
    {
        point_on = va_arg(list,char *);
        length += strlen(point_on);
        if( i == 0 )
        {
            strcpy(buffer,point_on);
            if( i != elements - 1)
            {
                strcat(buffer," ");
                length += 1;
            }
        }
        if( i != 0 )
        {
            strcat(buffer,point_on);
            if( i != elements - 1)
            {
                strcat(buffer," ");
                length += 1;
            }
        }
    }
    *(buffer + length ) = '\0';
    va_end(list);
    if( (length + 1) > size_of_buffer )
    {
        return 2;
    }
    return 0;
}

Co tutaj powinienem jeszcze dodać, aby to odpowiednio zabezpieczyć?

komentarz 20 maja 2020 przez j23 Mędrzec (194,920 p.)

A nie wiesz może jak mógłbym zabezpieczyć swój program na wypadek takiego testu?

Chodzi Ci o pustą linię? Nie widzę powodu, by jakoś specjalnie na nią reagować.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
0 odpowiedzi 398 wizyt
+1 głos
0 odpowiedzi 1,105 wizyt
0 głosów
1 odpowiedź 159 wizyt
pytanie zadane 19 kwietnia 2021 w C i C++ przez MrChick888 Obywatel (1,020 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...