Czytanie i pisanie do plików C

0
 #include <stdio.h>
 #include <stdlib.h>
 
int main ()
{
	FILE *wej;
	FILE *wyj;

	if ((wej=fopen("wej", "r"))==NULL) 
	{
		printf ("Nie mogę otworzyć pliku!\n");
		exit(1);
	}
	
	char *a;	
	fscanf(wej,"%s", a);
	printf ("%s\n",a);
	
	fclose (wej); 
	
	return 0;
}

Powyższy kod kompiluje się lecz po uruchomieniu daje błąd: Segmentation fault (core dumped), jaka jest niskopoziomowa przyczyna tego błędu?

7
    char *a;    
    fscanf(wej,"%s", a);

Musisz zaalokować pamięć dla wczytywanego stringa (np. za pomocą malloc()), albo użyć tablicy.

0

Jeszcze taka sprawa, dlaczego to:

 #include <stdio.h>
 #include <stdlib.h>
 
int main ()
{
	FILE *wej;
	FILE *wyj;

	if ((wej=fopen("wej", "r"))==NULL) 
	{
		printf ("Nie mogę otworzyć pliku!\n");
		exit(1);
	}
	
	char a;	
	fscanf(wej,"%s", a);
	printf ("%s\n",a);
	puts("\n");
	fclose (wej); 
	
	return 0;
}

działa i wypisuje "(null)
"?

4

Bo to co napisałeś zawiera niezdefiniowane zachowanie i po prostu jest źle (nie zrozumiałeś kq). Wersja poprawiona:

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

int main ()
{
    FILE *wej;
    FILE *wyj;

    if ((wej=fopen("wej", "r"))==NULL) 
    {
        perror("plik wejsciowy");
        exit(1);
    }

    char a[256]; 
    fscanf(wej,"%255s", a);
    printf ("%s\n",a);
    puts("\n");
    fclose (wej); 

    return 0;
}

https://wandbox.org/permlink/cqQyTim3vZkO31By

2
szybki_procesor napisał(a):

Jeszcze taka sprawa, dlaczego to:

 #include <stdio.h>
 #include <stdlib.h>
 
int main ()
{
	FILE *wej;
	FILE *wyj;

	if ((wej=fopen("wej", "r"))==NULL) 
	{
		printf ("Nie mogę otworzyć pliku!\n");
		exit(1);
	}
	
	char a;	
	fscanf(wej,"%s", a);
	printf ("%s\n",a);
	puts("\n");
	fclose (wej); 
	
	return 0;
}

działa i wypisuje "(null)
"?

Ale to nie działa. To jest UB. fscanf spodziewa się adresu zmiennej (adresu w pamięci), do którego ma wczytać łańcuch znakowy, w przypadku "%s" powinna być to tablica char. Ty przekazałeś pojedyńczą zmienna typu char. Nieznana zawartość zmiennej a typu char została zinterpretowana jako adres, gdzie ma być wczytany łańcuch znakowy. Jakby a było tablicą, to by "działało", bo ta tablica się aliasuje na wskaźnik i do takiej tablicy odczytany łańcuch znakowy zostałby skopiowany.
Z kolei wypisując reinterpretujesz zmienną typu char jako wskaźnik na pamięć łańcucha znakowego. Nie wiadomo co zostanie wypisane.

0

"działa" w sensie nie wywala błędu, nie chciałem tego nigdzie używać tylko byłem ciekaw dlaczego w przypadku u góry wywala błąd a w przypadku na dole, po dodaniu puts ("\n"); już nie.

1
char line[12+1];
fscanf(wej,"%12[^\n]s",a); // bezpiecznie do końca wiersza
    // wczytywanie daty w formacie DD:MM:YYYY
    char day[2+1],month[2+1],year[4+1],tmp;
    fscanf(wej,"%2[^:]s",day); // bezpiecznie do znaku :
    fscanf(wej,"%c%2[^:]s",&tmp,month); // bezpiecznie do znaku :
    fscanf(wej,"%c%4s",&tmp,year); // bezpiecznie do końca wiersza
    // tam gdzie działa bez `s` (patrz komentarz) da się wczytać w jednym poleceniu:
    char day[2+1]={},month[2+1]={},year[4+1]={};
    fscanf(stdin,"%2[^:]%*c%2[^:]%*c%4s",day,month,year);
2
szybki_procesor napisał(a):

"działa" w sensie nie wywala błędu, nie chciałem tego nigdzie używać tylko byłem ciekaw dlaczego w przypadku u góry wywala błąd a w przypadku na dole, po dodaniu puts ("\n"); już nie.

Brak błędów kompilacji w C, to jest baaaaardzo niewiele. Podczas wykonania, to błędów, niezdefiniowanych zachowań (UB - drugie u ciebie), wyjątków systemowych (jak na początku u ciebie) może się zdarzyć cała rozmaitość. W tym języku szczególnie dużo.
Najgorsze jest ukrycie się błędu (nie widać przejawów), początkujący dowodzą z tego, ze program jest bezbłędny. Trzeba podchodzić z wielką pokorą i wiedzą (a nie gdybać o języku "na czuja").

Funkcje o zmiennej ilości parametrów (rodzina xxxprintf i xxxscanf na przykład) podnosi poziom ryzyka.

5

Najlepiej jeśli w do procesu budowania doda flagi -Wall i -Werror.
Wtedy kompilator wyłapie mu 90% błędów popełnianych przez początkujących.

Polecam też podczas debugowania używać -fsanitize=address, żeby w czasie wykonania łapać błędy pamięci.

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