Programowanie strukturalne
- Wykład 8

Napisy
(łańcuchy znaków)

Napisy

Napis - ciąg składający się z co najmniej jednego znaku.

Znaki cudzysłowu nie są częścią łańcucha.

Język C nie posiada typu string/łańcuchowego. Wszystkie napisy traktowane są jako tablice typu char. Ostatnim znakiem w tablicy jest znak \0.

Znak a napis

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

int main()
{
    char a = 'q';
    char b[] = "q";
    return 0;
}

srtlen a sizeof

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

int main()
{
    char nap1[] = "Hello World";
    char nap2[50] = "Hello World";
    printf("%Iu\n",sizeof nap1);
    printf("%Iu\n",strlen(nap1));
    printf("%Iu\n",sizeof nap2);
    printf("%Iu\n",strlen(nap2));
    return 0;
}

Tablica a wskaźnik

#include <stdio.h>
#define NAPIS "jakiś tekst"

int main()
{
    char tab[] = NAPIS;
    const char *wsk = NAPIS;
    printf("adres napisu %p\n", "jakiś tekst");
    printf("adres tab: %p\n", tab);
    printf("adres wsk: %p\n", wsk);
    printf("adres NAPIS-u: %p\n", NAPIS);
    return 0;
}
#include <stdio.h>

int main()
{
    char nap1[] = "absddfvjskjf";
    char *nap2 = "oijefj";
    nap1[4] = 'M';
    *(nap1 + 7) = 'M';
    nap2[2]='3'; // czy to zawsze możliwe?
    return 0;
}

Kopiowanie napisu

#include <stdio.h>

int main()
{
    char * napis = "ab6sWR";
    char * kopia;
    kopia=napis;
    printf("%s\n",napis);
    printf("%p\n",napis);
    printf("%p\n",&napis);
    printf("%s\n",kopia);
    printf("%p\n",kopia);
    printf("%p\n",&kopia);
    return 0;
}

czy można to zrobić notacją tablicową?

Wczytywanie napisów

  • scanf

https://pl.wikibooks.org/wiki/C/scanf

https://en.cppreference.com/w/c/io/fscanf

  • gets

https://pl.wikibooks.org/wiki/C/gets

https://en.cppreference.com/w/c/io/gets

  • fgets

https://pl.wikibooks.org/wiki/C/fgets

https://en.cppreference.com/w/c/io/fgets

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

int main()
{
    int a;
    scanf("%i",&a);
    printf("%i\n",a);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int n,m;
    scanf("%d, %d",&n,&m);
    printf("%d %d\n",n,m);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char znak;
    scanf(" %c",&znak);
    printf("%c\n",znak);
    return 0;
}

Wskaźnik czy tablica?

#include <stdio.h>

int main()
{
    char * slowo;
    scanf("%s",slowo);
    printf("%s\n",slowo);
    return 0;
}
#include <stdio.h>

int main()
{
    char slowo[20];
    scanf("%s",slowo);
    printf("%s\n",slowo);
    return 0;
}
#include <stdio.h>

int main()
{
    char slowo[5];
    gets(slowo);
    printf("%s\n",slowo);
    puts(slowo);
    return 0;
}
  • wpisz różnej długości napisy (niektóre ze spacjami)
#include <stdio.h>

int main()
{
    char slowo[5];
    gets_s(slowo, 4*sizeof(char));
    printf("%s\n", slowo);
    puts(slowo);
    return 0;
}
  • nie działa w każdej konfiguracji
#include <stdio.h>

int main()
{
    char slowo[5];
    fgets(slowo,5,stdin);
    printf("%s\n",slowo);
    puts(slowo);
    fputs(slowo,stdout);
    return 0;
}

Różnice?

  • scanf - do znaku niedrukowanego, reszta do końca linii
  • gets - mało bezpieczna przy przepełnieniu
  • fgets - dodaje koniec linii na końcu napisu

Wyświetlanie napisów

  • printf

https://pl.wikibooks.org/wiki/C/printf

https://en.cppreference.com/w/c/io/fprintf

  • puts

https://pl.wikibooks.org/wiki/C/puts

https://en.cppreference.com/w/c/io/puts

  • fputs

https://pl.wikibooks.org/wiki/C/fputs

https://en.cppreference.com/w/c/io/fputs

#include <stdio.h>

int main()
{
    char tekst1[]="abc";
    char tekst2[]= {'a','b','c'};
    char tekst3[]="xyz";
    printf("%p\n",tekst1);
    printf("%p\n",tekst2);
    printf("%p\n",tekst3);
    puts(tekst1);
    puts(tekst2);
    puts(tekst3);
    return 0;
}
#include <stdio.h>

int main()
{
    char tekst1[]="abc";
    char tekst2[]= {'a','b','c'};
    char tekst3[]="xyz";
    puts(tekst1);
    puts(tekst2);
    puts(tekst3);
    return 0;
}
#include <stdio.h>

int main()
{
    char tekst1[]="abc";
    char tekst2[]= {'a','b','c'};
    char tekst3[]="xyz";
    fputs(tekst1,stdout);
    fputs(tekst2,stdout);
    fputs(tekst3,stdout);
    return 0;
}
#include <stdio.h>

int main()
{
    char tekst1[]="abc";
    char tekst2[]= {'a','b','c'};
    char tekst3[]="xyz";
    printf("%s",tekst1);
    printf("%s",tekst2);
    printf("%s",tekst3);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char buffer[20];
    int a=5;
    int b=7;
    sprintf(buffer,"%5d+%5d=%5d",a,b,a+b);
    printf("%s",buffer);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char buffer[20];
    int a=5;
    int b=7;
    snprintf(buffer,20*sizeof(char),"%5d+%5d=%5d",a,b,a+b);
    printf("%s",buffer);
    return 0;
}

Bibliografia

  • Richard Reese, Wskaźniki w języku C, Wydawnictwo Helion 2014.