I have an embedded board (beagleboard-xm) that runs ubuntu 12.04. I need to read a GPIO continuously to see if the value of the port changes. My code is herebelow:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
FILE *fp;
int main(void)
{
//linux equivalent code "echo 139 > export" to export the port
if ((fp = fopen("/sys/class/gpio/export", "w")) == NULL){
printf("Cannot open export file.\n");
exit(1);
}
fprintf( fp, "%d", 139 );
fclose(fp);
// linux equivalent code "echo low > direction" to set the port as an input
if ((fp = fopen("/sys/class/gpio/gpio139/direction", "rb+")) == NULL){
printf("Cannot open direction file.\n");
exit(1);
}
fprintf(fp, "low");
fclose(fp);
// **here comes where I have the problem, reading the value**
int value2;
while(1){
value2= system("cat /sys/class/gpio/gpio139/value");
printf("value is: %d\n", value2);
}
return 0;
}
the code above reads the port continuously (0 by default), however, when I change the port as 1, system call output the correct value, however printf still prints 0 as an output. What is the problem with value2 that does not store the value that system() outputs.
If I use the code below instead of while loop above, I get an error about opening the value file (Cannot open value file.), if I put the fopen line outside of while loop, it does not show the changes in the value file.
char buffer[10];
while(1){
if ((fp = fopen("/sys/class/gpio/gpio139/value", "rb")) == NULL){
printf("Cannot open value file.\n");
exit(1);
}
fread(buffer, sizeof(char), sizeof(buffer)-1, fp);
int value = atoi(buffer);
printf("value: %d\n", value);
}
My question: how do I need to fix the code? or how should I read the value file?
As an additional info that I wonder: what is the difference to e.g. export the port by system("echo 139 > /sys/class/gpio/export") and fp = fopen("/sys/class/gpio/export","w"); fprintf(fp,"%d",139); which method do you suggest me to use? Why?
Thank you in advance.
The system() function returns the return value of cat, which is 0. It does not return the standard output from cat, which is what you were expecting.
I think the problem with your second bit of code is that you're not calling fclose(). Since you're running in a tight loop, you almost immediately exceed the number of open files allowed.
So, call fclose(), and think about putting a sleep() in there too.
When reading a file in C, your position in the file changes as you read it. For example, if you were to open a file with the contents:
First Line
Second Line
Third Line
and run this program:
char buffer[1024];
while(fgets(buffer, sizeof(buffer), theFile))
{
printf("Buffer: %s", buffer);
}
It would print:
First Line
Second Line
Third Line
As you read each line, the position in the file changes to the next line.
In your program, after reading the value the first time, you are trying to read the empty space in the file, instead of the value you want.
The solution to your problem is to move fopen outside of the while loop, but call fseek to reset your position to the start of the file each time through the loop.
To use fseek, you need to pass it a file pointer, byte offset and seek point. Here you call it on your file, with a 0 byte offset from the waypoint SEEK_SET, which indicates the start of the file.
fseek(theFile, 0, SEEK_SET);
Related
I'm trying to read a binary file of 32 bytes in C, however I'm keep getting "segmentation fault (code dumped)" when I run my program,
it would be great if somebody can help me out by pointing where did I go wrong?.
my code is here below:
int main()
{
char *binary = "/path/to/myfiles/program1.ijvm";
FILE *fp;
char buffer[32];
// Open read-only
fp = fopen(binary, "rb");
// Read 128 bytes into buffer
fread (buffer, sizeof(char), 32, fp);
return 0;
}
It's because of the path. Make sure that "/path/to/myfiles/program1.ijvm" points to an existing file.
You should always check the return value of fopen.
\\Open read-only
fp = fopen(binary, "rb");
if(fp==NULL){
perror("problem opening the file");
exit(EXIT_FAILURE);
}
Notice also that you are reading 32 bytes in your buffer and not 128 as your comment says.
You must check the return result from fopen().
I'm assuming you are getting the segfault in the fread() call because your data file doesn't exist, or couldn't be opened, and you are trying to work on a NULL FILE structure.
See the following safe code:
#include <stdio.h>
#include <stdint.h>
#define SIZE_BUFFER 32
int main()
{
char *binary = "data.txt";
FILE *fp = NULL;
char buffer[SIZE_BUFFER];
// Open read-only
fp = fopen(binary, "rb");
// Read SIZE_BUFFER bytes into buffer
if( fp )
{
printf("Elements read %ld\n", fread (buffer, sizeof(char), SIZE_BUFFER, fp));
fclose(fp);
}
else
{
// Use perror() here to show a text description of what failed and why
perror("Unable to open file: ");
}
return 0;
}
When I execute this code it doesn't crash and will print the number of elements read if the file is opened or it will print "Unable to open file" if the file could not be opened.
As mentioned in the comments you should also close the file being exiting. Another thing you can do is the following:
FILE *fp = fopen(.....);
Instead of declaring and assigning in two separate steps.
There are two possible reasons
The fopen(3) function failed due to some reason, which means fp is NULL, and then you are trying to use the null-pointer in fread(3). This can crash. #OznOg has already given a subtle hint to look into this direction.
If the fopen call is a success (i.e. fp is non-NULL after calling fopen), the code can still crash because you are reading 32 chars into the variable binary, while binary has been initialized with only 30 chars.
I created a function that is successfully reading the binary file but it is not printing as I wanted.
The function:
void print_register() {
FILE *fp;
fp = fopen("data.bin", "rb");
if (fp == NULL) {
error_message("Fail to open data.bin for reading");
exit(0);
}
reg buffer;
while (EOF != feof(fp)) {
fread(&buffer, sizeof(reg), 1, fp);
printf("%s %d %d\n", buffer.name, buffer.age, buffer.id);
}
fclose(fp);
}
Note: reg is a typedef for a struct:
typedef struct registers reg;
struct registers {
char name[30];
int age;
int id;
char end;
};
Function for writing the file:
void register_new() {
system("clear");
reg buffer;
FILE *fp;
fp = fopen("data.bin", "ab");
if (fp == NULL) {
error_message("Error opening file data.bin");
exit(0);
}
write_register(buffer);
fwrite(&buffer, sizeof(reg), 1, fp);
fclose(fp);
}
Posting a printscreen of what was print to be more helpful:
As you can see on image, after the "p" (command for printing) is where should be the name, age and id of the struct.
In register_new(), you have to send the address of buffer in order for write_register() to work properly (right now you're giving it a copy of buffer).
Replace:
write_register(buffer);
with:
write_register(&buffer);
Then correct write_register to take and work with an address instead of a structure.
This might help you understand what's going on: http://fresh2refresh.com/c-programming/c-passing-struct-to-function
Your reading loop is incorrect. Don't use feof(), it can only tell is you have reached the end of file after a read attempt failed and it might not return EOF anyway, it is only specified as returning 0 or non 0. Use this instead:
while (fread(&buffer, sizeof(reg), 1, fp) == 1) {
printf("%s %d %d\n", buffer.name, buffer.age, buffer.id);
}
fread returns the number of items successfully read. Here you request to read 1 item of size sizeof(reg), if the item was read successfully, fread will return 1, otherwise it will return 0 (in case of a read error or end of file reached).
Your screenshot shows a syntax error, which you seem to have fixed now. Remove that, it is not helping.
In your function register_new, you are writing an uninitialized structure reg to the file, no wonder it does not contain anything useful when you read it back from the file. And for what it is worth, opening this file in binary mode is the correct thing to do since it contains binary data, namely the int members of the structure.
The reg passed to fwrite is indeed uninitialized. write_register gets a copy of this uninitialized structure by value, and probably modifies this copy, but this does not affect the local structure in register_new. You should modify write_register() to take a pointer to the structure. Unlike C++, there is no passing by reference in C.
I'm working on a project, and I can't seem to figure out why a piece of my function for finding prime numbers won't run. Essentially, I want to code to first check the text file log for any previously encountered prime numbers, but no matter what I put for the while-loop containing fscanf(), it seems like my code never enters it.
int filePrime(int a) {
int hold = 0;
FILE *fp = fopen("primes.txt", "a+");
if (fp == NULL) {
printf("Error while opening file.");
exit(2);
}
/*
the while loop below this block is the one with the issue.
on first run, it should skip this loop entirely, and proceed
to finding prime numbers the old-fashioned way, while populating the file.
instead, it is skipping this loop and proceeding right into generating a
new set of prime numbers and writing them to the file, even if the previous
numbers are already in the file
*/
while (fscanf(fp, "%d", &hold) == 1){
printf("Inside scan loop.");
if (hold >= a) {
fclose(fp);
return 1;
}
if (a % hold == 0) {
fclose(fp);
return 0;
}
}
printf("Between scan and print.\n");
for (; hold <= a; hold++) {
if (isPrime(hold) == 1) {
printf("Printing %d to file\n", hold);
fprintf(fp, "%d\n", hold);
if (hold == a)
return 1;
}
}
fclose(fp);
return 0;
}
I have tried all sorts of changes to the while-loop test.
Ex. != 0, != EOF, cutting off the == 1 entirely.
I just can't seem to get my code to enter the loop using fscanf.
Any help is very much appreciated, thank you so much for your time.
In a comment, I asked where the "a+" mode leaves the current position?
On Mac OS X 10.11.4, using "a+" mode opens the file and positions the read/write position at the end of file.
Demo code (aplus.c):
#include <stdio.h>
int main(void)
{
const char source[] = "aplus.c";
FILE *fp = fopen(source, "a+");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s\n", source);
}
else
{
int n;
char buffer[128];
fseek(fp, 0L, SEEK_SET);
while ((n = fscanf(fp, "%127s", buffer)) == 1)
printf("[%s]\n", buffer);
printf("n = %d\n", n);
fclose(fp);
}
return(0);
}
Without the fseek(), the return value from n is -1 (EOF) immediately.
With the fseek(), the data (source code) can be read.
One thing slightly puzzles me: I can't find information in the POSIX fopen() specification (or in the C standard) which mentions the read/write position after opening a file with "a+" mode. It's clear that write operations will always be at the end, regardless of intervening uses of fseek().
POSIX stipulates that the call to open() shall use O_RDWR|O_CREAT|O_APPEND for "a+", and open() specifies:
The file offset used to mark the current position within the file shall be set to the beginning of the file.
However, as chux notes (thanks!), the C standard explicitly says:
Annex J Portability issues
J.3 Implementation-defined behaviour
J.3.12 Library functions
…
Whether the file position indicator of an append-mode stream is initially positioned at
the beginning or end of the file (7.21.3).
…
So the behaviour seen is permissible in the C standard.
The manual page on Mac OS X for fopen() says:
"a+" — Open for reading and writing. The file is created if it does not exist. The stream is positioned at the end of the file. Subsequent writes to the file will always end up at the then current end of file, irrespective of any intervening fseek(3) or similar.
This is allowed by Standard C; it isn't clear it is fully POSIX-compliant.
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "ff.txt"
int main() {
char x[10],y[10];
FILE *fp;
fp = fopen(FILE_NAME, "r+");
if (fp == NULL) {
printf("couldn't find %s\n ",FILE_NAME);
exit(EXIT_FAILURE);
}
fprintf(fp,"Hello2 World\n");
fflush(fp);
fscanf(fp,"%s %s",x,y);
printf("%s %s",x,y);
fclose(fp);
return 0;
}
Here's a boiled down version of what I am trying to do. This code doesn't print anything in the console. If I remove the fprintf call, it prints the first 2 strings in the file, for me its Hello2 World. Why is this happening? Even after I fflush the fp?
After fprintf(), the file pointer points to the end of the file. You can use fseek() to set the filepointer at the start of the file:
fprintf(fp,"Hello2 World\n");
fflush(fp);
fseek(fp, 0, SEEK_SET);
fscanf(fp,"%s %s",x,y);
Or even better as suggested by #Peter, use rewind():
rewind(fp);
rewind:
The end-of-file and error internal indicators associated to the stream
are cleared after a successful call to this function, and all effects
from previous calls to ungetc on this stream are dropped.
On streams open for update (read+write), a call to rewind allows to
switch between reading and writing.
It is always best to check the return code of fscanf() too.
To avoid buffer overflow, you can use:
fscanf(fp,"%9s %9s",x,y);
Trying to learn C. Want to read the first line of a text file, my code is:
#include <stdio.h>
int main()
{
FILE *in = fopen("test.txt", "rt");
// read the first line from the file
char buffer[100];
fgets(buffer, 20, in);
printf("first line of \"test.txt\": %s\n", buffer);
fclose(in);
return 0;
}
I'm doing this in xCode. I get a exc bad access error.
test.txt definitely exists. It has one line that says "this is a text file"
try this after fopen() call:
if(in == NULL){
printf("Can't read teste.txt because: %s.\n", strerror(errno));
return 1;
}
and add the headers:
#include <errno.h>
#include <string.h>
The code looks fine, so my guess is that the program is not run in the same working directory as the file. Try placing the file in, say, /tmp/test.txt and use absolute path in fopen.
You don't check if the FILE is NULL. It may not be opened for a several reasons.