I'm using the following code below and I'm receiving a Thread 1: EXC_BAD_ACCESS (code=1, address=0x68) error. What are some ways I can execute this better? I'm simply loading a txt file that has roughly 500000 numbers and they are each on a new line. I've looked at a few resources how to do this, but I end up with these oddities. I'm hoping a c guru can help me out.
#include <stdio.h>
#include <time.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define COUNT_ARRAY_LENGTH 10
#define MAX_NUMBER 500001
int *load_file(){
FILE *file;
file = fopen("somefile.txt", "r");
int a[MAX_NUMBER];
int i=0;
int num;
while(fscanf(file, "%d", &num) > 0) {
a[i] = num;
i++;
}
fclose(file);
return a;
}
int main(int argc, const char *argv[])
{
int *a;
a = load_file();
for(int i = 0; i < MAX_NUMBER; i++){
printf("%d\n", a[i]);
}
return 0;
}
Converting comments into an answer.
My immediate guess would be that you're failing to open the file — an error you don't check for and must always check for. Files go AWOL, or the program is run from the wrong directory, or they have the wrong permissions.
if (file == NULL)
{
fprintf(stderr, "Failed to open file '%' for reading\n", "somefile.txt");
exit(EXIT_FAILURE);
}
The repeated literal for the file name shows why you should never pass a string literal as the file name to fopen(); you should have a variable so that you can report the file name in the error message too, without repeating yourself.
const char *filename = "somefile.txt";
if ((file = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Failed to open file '%' for reading\n", filename); n.
exit(EXIT_FAILURE);
}
In fact, you should probably pass the name of the file to be loaded to the load_file() function so that you can more easily change it (by command line arguments, for example). That is as well as passing the array, and the size of the array. That gives you a more generic function, one more easily adapted to other uses.
You could also #include <errno.h> and #include <string.h> and use strerror(errno) to print the system error message to give more help to the user (but knowing the file name is a huge step in the right direction).
Also, you should have while (i < MAX_NUMBER && fscanf(file, "%d", &num) > 0) so you don't overflow the array.
Also, you're returning the address of the local array in load_file() — you can't do that safely. Define the array in main() and pass the pointer as a parameter. Your main() also assumes that the array was filled. Revise load_file() to return how many numbers were loaded so you don't access unloaded numbers.
Putting all those changes together might yield:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUMBER 500001
static size_t load_file(const char *filename, size_t arrsiz, int *array)
{
FILE *file;
if ((file = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
exit(EXIT_FAILURE);
}
size_t i = 0;
int num;
while (i < arrsiz && fscanf(file, "%d", &num) > 0)
array[i++] = num;
fclose(file);
return i;
}
int main(void)
{
int a[MAX_NUMBER];
size_t num = load_file("somefile.txt", MAX_NUMBER, a);
for (size_t i = 0; i < num; i++)
printf("%d\n", a[i]);
return 0;
}
That's been compiled but not run.
You could process a command-line argument like this:
int main(int argc, char **argv)
{
if (argc > 2)
{
fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *filename = (argc == 2) ? argv[1] : "somefile.txt";
int a[MAX_NUMBER];
size_t num = load_file(filename, MAX_NUMBER, a);
for (size_t i = 0; i < num; i++)
printf("%d\n", a[i]);
return 0;
}
Or you could allow more than one argument and iterate over them all.
Sometimes, it's better to do the file opening and closing in the main() and pass the open file stream to the function. You can then read from stdin if there are no command-line arguments. The options are legion!
Related
Need help getting display_stream function to read from stdin in Shell. When I type './kittycat' in Shell I am getting blank when it should read from stdin. Everything else works which is for one or more arguments it reads the text files (./kittycat test.txt test2.txt) and if I put './kittycat error.txt' it will say error file not found.' I am just missing a way to read from stdin using the function display_stream. Including Screenshots of shell output vs what is expected.
[enter image description here][1]#include <stdio.h>
#include <stdlib.h>
void display_stream(FILE *fptr);
int
main(int argc, char *argv[])
{
int i;
// if no args given, read from stdin (just like shell/cat)
if (argc < 2)
display_stream(stdin);
for (i = 1; i < argc; i++) {
FILE *fptr = fopen(argv[i], "r");
if (fptr == 0) {
printf("error: file not found.");
continue;
}
display_stream(fptr);
fclose(fptr);
}
return 0;
}
void
display_stream(FILE *fptr)
{
int x;
/* read one character at a time from file, stopping at EOF,
which indicates the end of the file. */
while ((x = fgetc(fptr)) != EOF)
putchar(x);
}
MY output
What is expected
Check argc to decide if the program should read from stdin or should open argv[i] to open the file.
Here's the refactored [and annotated] code:
#include <stdio.h>
#include <stdlib.h>
void display_stream(FILE *fptr);
int
main(int argc, char *argv[])
{
int i;
// if no args given, read from stdin (just like shell/cat)
if (argc < 2)
display_stream(stdin);
for (i = 1; i < argc; i++) {
FILE *fptr = fopen(argv[i], "r");
if (fptr == 0) {
printf("error: file not found.");
}
else {
display_stream(fptr);
#if 1
fclose(fptr);
#endif
}
}
return 0;
}
void
display_stream(FILE *fptr)
{
int x;
/* read one character at a time from file, stopping at EOF,
which indicates the end of the file. */
while ((x = fgetc(fptr)) != EOF) {
printf("%c", x);
}
// don't close this here -- let caller do it (e.g. stdin should _not_ be
// closed and only caller knows whether the stream is stdin or not)
#if 0
fclose(fptr);
#endif
}
Here's a slightly more cleaned up version:
#include <stdio.h>
#include <stdlib.h>
void display_stream(FILE *fptr);
int
main(int argc, char *argv[])
{
int i;
// if no args given, read from stdin (just like shell/cat)
if (argc < 2)
display_stream(stdin);
for (i = 1; i < argc; i++) {
FILE *fptr = fopen(argv[i], "r");
if (fptr == 0) {
printf("error: file not found.");
continue;
}
display_stream(fptr);
fclose(fptr);
}
return 0;
}
void
display_stream(FILE *fptr)
{
int x;
/* read one character at a time from file, stopping at EOF,
which indicates the end of the file. */
while ((x = fgetc(fptr)) != EOF)
putchar(x);
}
Move fclose out of display_stream, it doesn’t belong there. Place it just after the call to display_stream.
Add display_stream(stdin) to main (without fclose this time, stdin shouldn’t be closed), before or after the loop. It should just work.
It will probably copy from stdin line-by-line but that’s due to buffering outside of the program which is not that easy to disable AFAIK.
Also, printf( "%c", x ) could be putchar(x)
I wanna do this:
Progam1 | Program2
I wanna use the output of the first program as input(stdin) for the program2 to do some calculations.
for now this is what i have in program 2
int main(int argc, char *argv[]) {
char userInput[100];
int num[100];
FILE *cmdLn = stdin;
if (argc > 2) {
fprintf(stderr, "Usage: %s [<file>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2) {
cmdLn = fopen(argv[1], "r");
if (!cmdLn) {
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
int numInput[100];
for (int i = 0; i < 100; i++) {
fscanf(cmdLn, "%d", &numInput[i]);
printf("%d\n", 2*numInput[i]);
}
if (cmdLn != stdin) {
fclose(cmdLn);
}
exit(EXIT_SUCCESS);
}
program 1 just creates several numbers per row. I want to use those numbers in program 2 to double them and print the result.
What am I missing here?
I am reading from with fgets from *file which is getting input from stdin
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char userInput[100];
int numInput[100];
FILE *file = stdin;
if (argc > 2) {
fprintf(stderr, "Usage: %s [<file>]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2) {
file = fopen(argv[1], "r");
if (!file) {
perror(argv[0]);
exit(EXIT_FAILURE);
}
}
int num[100];
while (fgets(userInput, sizeof(userInput), file))
{
num[i] = atoi(userInput);
printf("%d\n", 2*num[i]);
i++;
}
if (file != stdin) {
fclose(file);
}
exit(EXIT_SUCCESS);
}
the shell redirection works, but not exactly how I want.
Program 1 gives me 10random int numbers.
when I get 10 different numbers from program 1 and pipe its output to program 2 I get new 10 random values and not the output of program 1 before.
program 2 should calculate those(e.g. multiply by 2).
Maybe the problem lies in program 1:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXNUM 1000
int main(int argc,char *argv[]) {
char *userInput[10];
time_t t;
int num = atoi(argv[1]);
srand(time(NULL));
for (int i = 0; i <= num; i++) {
printf("%d\n", rand() % MAXNUM);
}
return 0;
}
the problem is that it generates new random numbers. But I want to use the output of this program and multiply it with 2 with program 2
I think I fixed it! Yeehawww!
It was the srand() causing this problem. Uncommenting that solved it.
I'm trying to open a file using command line arguments and read the numbers I have in my 'testdata' file in reverse The numbers in the test data file consist of:
2
20
200
2000
20000
-2
-20
-200
-20000.
Here is the code I have written so far. The file prints out, obviously not in reverse. I'm assuming I'm just missing a for loop in here somewhere. I'm also considering that maybe I should be using fscanf instead of fgets. Any input is appreciated.
#include <stdio.h>
#define MAX_NUMS 1000
int main(int argc, char *argv[]) {
Int a, n;
char buf[MAX_NUMS];
Int array[MAX_NUMS];
file *pt;
if (argc < 2) {
printf("Usage %s <files..>\n");
}
if ((pt = fopen(argv[1], "r")) == NULL) {
printf("Unable to open %s for reading.\n", argv[1]);
Return 1;
}
while (fgets(buf, MAX_NUMS, pt) != NULL){
printf("%s", buf);
}
for(j = 0; j < MAX_NUMS; j++){
If(fscanf(pt, "%d", &array[a]) != 1);
Break;
For(a = n; a--> 0;){
Printf("%d", array[a]);
}
fclose(pt);
retuern 0;
}
Use while(fscanf("%d", &n)){ a[i++] = n; } initiate i with 0 before and declare a as an integer array. Later while printing, printing it in reverse order. It is not possible to read from reverse order, though you can go to the end of the file using fseek().
There are some problems in your code:
the stream type is spelled FILE.
you do not return from the main() function in case of errors. The program keeps going and you have undefined behavior.
there is a missing argument in the first printf().
there is a typo on the return statement.
You could define the maximum number of numbers to handle, define an array for the numbers and use a loop index to store the numbers and later print them in reverse order.
Here is an example:
#include <stdio.h>
#define MAX_NUMBERS 1000
int main(int argc, char *argv[]) {
int array[MAX_NUMBERS];
int i, n;
FILE *pt;
if (argc < 2) {
printf("Usage %s <files..>\n", argv[0]);
return 1;
}
if ((pt = fopen(argv[1], "r")) == NULL) {
printf("Unable to open %s for reading.\n", argv[1]);
return 1;
}
for (n = 0; n < MAX_NUMBERS; n++) {
if (fscanf(pt, "%d", &array[n]) != 1)
break;
}
for (i = n; i-- > 0;) {
printf("%d\n", array[i]);
}
fclose(pt);
return 0;
}
I have to create a function that reads a file called grwords.txt containing around 540000 words which are written in Greek letters.
I have to convert these words to uppercase and fill an array called char **words.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <ctype.h>
void fp();
int main(int argc, char *argv[]) {
SetConsoleOutputCP(1253);
fp();
return 0;
}
void fp(){
char **words;
words = malloc(546490 * sizeof(int *));
for (i = 0; i < 546490; i++)
words[i] = malloc(24 * sizeof(int));
FILE *file;
char *word;
size_t cnt;
file = fopen("grwords.txt", "rt");
if (file == NULL){
printf("File cannot be opened.\n");
exit(1);
}
cnt = 0;
while (1==fscanf(file, "%24s",word)){
if (cnt == 546490)
break;
strcpy(words[cnt++], word);
}
fclose(file);
}
I'm still trying to figure out pointers. I know that & makes a pointer from a value and * a value from a pointer. Updated the program and it successfully fills the array with the words from the file! I still have no idea how to convert Greek lowercase to uppercase.
Handling Greek words can be dependent on your platform.
First of all, you need to understand how file handling works. Here is what I wrote:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bufSize 1024 // max lenght of word
// we are going to receive the .txt from cmd line
int main(int argc, char *argv[])
{
FILE *fp;
// Assume file has max 10 words
const size_t N = 10;
// Allocate a 2D array of N rows
// and bufSize columns.
// You can think of it like an array
// of N strings, where every string
// has, at most, bufSize length.
char buf[N][bufSize];
// make sure we got the .txt
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
// open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
// we will use that for toupper()
char c;
// counters
int i = 0, j;
while (fscanf(fp, "%1024s", buf[i]) == 1)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
// print what we read
printf("%s\n", buf[i]);
j = 0;
// while we are on a letter of word placed
// in buf[i]
while (buf[i][j])
{
// make the letter capital and print it
c = buf[i][j];
putchar (toupper(c));
j++;
}
i++;
printf("\ndone with this word\n");
}
// close the file
fclose(fp);
return 0;
}
For this test.txt file:
Georgios
Samaras
Γιώργος
Σαμαράς
the code would run as:
./exe test.txt
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
Γιώργος
done with this word
Σαμαράς
Σαμαράς
done with this word
As you can see, I could read the Greek words, but failed to convert them in upper case ones.
Once you got how file handling goes, you need to use wide characters to read a file with Greek words.
So, by just modifying the above code, we get:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t buf[N][bufSize];
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
return 0;
}
And now the output is this:
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
ΓΙΏΡΓΟΣ
done with this word
Σαμαράς
ΣΑΜΑΡΆΣ
done with this word
I see that you may want to create a function which reads the words. If you need a simple example of functions in C, you can visit my pseudo-site here.
As for the 2D array I mentioned above, this picture might help:
where N is the number of rows (equal to 4) and M is the number of columns (equal to 5). In the code above, N is N and M is bufSize. I explain more here, were you can also found code for dynamic allocation of a 2D array.
I know see that you are on Windows. I tested the code in Ubuntu.
For Windows you might want to take a good look at this question.
So, after you read all the above and understand them, you can see what you asked for with dynamic memory management.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
wchar_t **get(int N, int M);
void free2Darray(wchar_t** p, int N);
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t** buf = get(N, bufSize);
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
// NEVER FORGET, FREE THE DYNAMIC MEMORY
free2Darray(buf, N);
return 0;
}
// We return the pointer
wchar_t **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
wchar_t **table;
table = malloc(N*sizeof(wchar_t *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(wchar_t) );
return table;
}
void free2Darray(wchar_t** p, int N)
{
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
Note that this code is expected to work on Linux (tested on Ubuntu 12.04), not on Windows (tested on Win 7).
I'm trying to read data from a text file and copy them into an array, but my code doesn't work. This is the code:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
FILE *data;
data = fopen(argv[1], "r");
.......
fclose(data);
}
and when I replace
data = fopen(argv[1], "r");`
with
data = fopen("(the file name)", "r");
it works.
this is the full code
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
i=0;
FILE *data;
data = fopen(argv[1], "r");
while (!feof(data)) {
fscanf(data, "%i", &aa[i]);
i++;
}
fclose(data);
printf("%i\n", aa[0]);
}
and the text file is
3
2 1
2 2
2 3
You should always write basic error checking code for anything which might reasonably fail, e.g.:
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int i;
FILE *data;
if (argc < 2)
{
fprintf(stderr, "Missing arguments: %s\n", usage);
exit(1);
}
data = fopen(argv[1], "r");
if (data == NULL)
{
fprintf(stderr, "fopen('%s') failed, errno = %d, argv[1], errno);
exit(2);
}
.......
fclose(data);
return (0);
}
This way if fopen fails then (a) you won't crash and (b) you will get some useful info as to why the file was not opened.
You might be passing the file which is not available in the current directory.
Give the valid file directory with file name as argument
check for null after 'fopen'
compile with gcc -g -Wall main.c
and use gdb debugger to identify the error
You should pass filename while running the code.
./a.out file.txt.
If file.txt does not exist then it will throw error as segmentation fault.
Try this code, its working
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
int j = 0;
int aa[100]; //declare an int array to store the data, as you are retrieving using %i
i=0;
FILE *data;
data = fopen(argv[1], "r");
while (!feof(data)) {
fscanf(data, "%i", &aa[i]);
i++;
}
i--;
fclose(data);
for(j; j < i; j++)
printf("%i\n", aa[j]);
}
in file.txt give whatever data you are giving.
and while running pass ./a.out file.txt
See to it that file.txt is in same folder or give whole path