I have an embedded board (beagleboard-xm) that runs ubuntu 12.04, I would like to read one GPIO input if it is logic 1 or 0. How can I implement cat /sys/class/gpio/gpio139/value in C? (value file stores 0 or 1)
I open the file by:
FILE *fp;
fp = fopen("/sys/class/gpio/gpio139/value", "rb");
what do I need to do next?
If you want to read one character, try this:
int value = fgetc(fp);
/* error checking */
value = value - '0';
You can read one byte, or until eof:
char buffer[32]; // Very long number!
if (NULL == (fp = fopen(FILENAME, "rb")))
{
// TODO: return a suitable error/perror
return -1;
}
bytesread = fread(buffer, sizeof(char), sizeof(buffer)-1, fp);
fclose(fp);
if (!bytesread)
{
// Nothing at all was read
// TODO: return error
return -2;
}
// This is in case you want the byte interpreted from ASCII
// otherwise you'd just return buffer[0], or (*(DATATYPE *)buffer)[0].
buffer[bytesread] = 0x0;
return atol(buffer);
This code is actually not that general, in that many hardware devices will implement a blocking data channel - that is, if you try to read more data than it's there, the fread will block until data becomes available. In such a case, just dimension the buffer to the maximum number of bytes you need, plus one.
The plus one, and the corresponding -1 in the fread, are only there for the case in which the data you read is rendered as ASCII, i.e., "128" is three ASCII bytes "1", "2", "8" and maybe even a carriage return, instead of a binary 0x80. In this case, the buffer is zero-terminated to make it a C string on which atol may operate to retrieve a decimal number.
If what is needed is a binary value, then no such conversion is needed, and one can read the full buffer without adjustments, avoid setting the last plus one byte to zero, and just return a cast value from the buffer; or buffer[0] if only one byte is needed.
After attempting to open the file, you check that the fopen() succeeded.
Then you can use any of the stdio functions to read the data:
getc()
fgetc()
fgets()
fread()
and probably others too. You might be looking at the scanf() family, but most probably won't be using them, for example. Which is most appropriate depends on the data that is read; is it text or is it binary. If it is a single character, then getc(); if it is text and line-oriented, maybe fgets(); if binary, probably fread().
If you have access to your Linux headers, than I would recommend you to access GPIO using Linux API.
Include this in your file:
#include <linux/gpio.h>
Now you have access to functions like:
int gpio_is_valid(int number);
int gpio_get_value(unsigned gpio);
void gpio_set_value(unsigned gpio, int value);
In your case you can just write this:
int io_ret = -1;
if (gpio_is_valid(139))
io_ret = gpio_get_value(139);
i think it will be better if you used:
system("echo /sys/class/gpio/gpio139/value >> temp.txt ");
after that it is easy you can just extract the value from temp.txt which will be either 0 or 1
Related
I'm trying to read characters from a file and count the frequency of a particular word in a file using system calls, but the behavior of one of my read() calls is confusing me. This is the code that I've written:
int counter, seekError,readVal;
counter = 0;
char c[1];
char *string = "word";
readVal = read(fd,c,1);
while (readVal != 0){ // While not the end of the file
if(c[0] == string[0]) { // Match the first character
seekError = lseek(fd,-1,SEEK_CUR); // After we find a matching character, rewind to capture the entire word
char buffer[strlen(string)+1];
buffer[strlen(string)] = '\0';
readVal = read(fd,buffer,strlen(string)); // This read() does not put anything into the buffer
if(strcmp(lowerCase(buffer),string) == 0)
counter++;
lseek(fd,-(strlen(string)-1),SEEK_CUR); // go back to the next character
}
readVal = read(fd,c,1);
}
In all the read calls that I use, I am able to read characters with no problem from my file. However, the readVal = read(fd,buffer,strlen9string)); line never puts anything into buffer, no matter how I try to read the characters. Is there anything going on behind the scenes that would explain this kind of behavior? I've tried running this code on different machines as well, but I still get nothing in buffer at that line.
It shouldn't be necessary to cast -1 into the off_t type. It looks like your real bug is that you didn't include <unistd.h> so lseek wasn't properly declared when you used it. Either that or there's a serious bug in your system's implementation of lseek.
The problem here was that the -1 in the seekError = lseek(fd,-1,SEEK_CUR); line was being interpreted as 4294967295. After casting it into the off_t type, the system interpreted the offset as -1 instead of the large number.
So the corrected line is: seekError = lseek(fd,(off_t)-1,SEEK_CUR);
I'm trying to read a file and replace every char by it's corresponding char up one in ASCII table. It opens the file properly but keep on reading the first character.
int main(int argc, char * argv[])
{
FILE *input;
input = fopen(argv[2], "r+");
if (!input)
{
fprintf(stderr, "Unable to open file %s", argv[2]);
return -1;
}
char ch;
fpos_t * pos;
while( (ch = fgetc(input)) != EOF)
{
printf("%c\n",ch);
fgetpos (input, pos);
fsetpos(input, pos-1);
fputc(ch+1, input);
}
fclose(input);
return 1;
}
the text file is
abc
def
ghi
I'm pretty sure it's due to the fgetpos and fsetpos but if I remove it then it will add the character at the end of the file and the next fgetc will returns EOF and exit.
You have to be careful when dealing with files opened in update mode.
C11 (n1570), ยง 7.21.5.3 The fopen function
When a file is opened with update mode ('+' as the second or third character in the
above list of mode argument values), both input and output may be performed on the
associated stream.
However, output shall not be directly followed by input without an
intervening call to the fflush function or to a file positioning function (fseek,
fsetpos, or rewind), and input shall not be directly followed by output without an
intervening call to a file positioning function, unless the input operation encounters end-of-file.
So your reading might look something like :
int c;
while ((c = getc(input)) != EOF)
{
fsetpos(/* ... */);
putc(c + 1, input);
fflush(input);
}
By the way, you will have problems with 'z' character.
procedure for performing random access such
positioned the record
reading of the record
positioned the record
update(write) the record
do flush (to finalize the update)
The following code is a rewrite in consideration to it.
#include <stdio.h>
#include <ctype.h>
int main(int argc, char * argv[]){
FILE *input;
input = fopen(argv[1], "rb+");
if (!input){
fprintf(stderr, "Unable to open file %s", argv[1]);
return -1;
}
int ch;
fpos_t pos, pos_end;
fgetpos(input, &pos);
fseek(input, 0L, SEEK_END);
fgetpos(input, &pos_end);
rewind(input);
while(pos != pos_end){
ch=fgetc(input);
if(EOF==ch)break;
printf("%c",ch);
if(!iscntrl(ch) && !iscntrl(ch+1)){
fsetpos(input, &pos);
fputc(ch+1, input);
fflush(input);
}
pos += 1;
fsetpos(input, &pos);
}
fclose(input);
return 1;
}
I really suspect the problem is here:
fpos_t * pos;
You are declaring a pointer to a fpos_t which is fine but then, where are the infomation stored when you'll retrieve the pos?
It should be:
fpos_t pos; // No pointer
...
fgetpos (input, &pos);
fsetpos(input, &pos); // You can only come back where you were!
Reading the (draft) standard, the only requirement for fpos_t is to be able to represent a position and a state for a FILE, it doesn't seem that there is a way to move the position around.
Note that the expression pos+1 move the pointer, does not affect the value it points to!
What you probably want is the old, dear ftell() and fseek() that will allow you to move around. Just remember to open the file with "rb+" and to flush() after your fputc().
When you'll have solved this basic problem you will note there is another problem with your approach: handling newlines! You most probably should restrict the range of characters you will apply your "increment" and stipulate that a follows z and A follows Z.
That said, is it a requirement to do it in-place?
7.21.9.1p2
The fgetpos function stores the current values of the parse state (if
any) and file position indicator for the stream pointed to by stream
in the object pointed to by pos. The values stored contain unspecified
information usable by the fsetpos function for repositioning the
stream to its position at the time of the call to the fgetpos
function.
The words unspecified information don't seem to inspire confidence in that subtraction. Have you considered calling fgetpos prior to reading the character, so that you don't have to do a non-portable subtraction? Additionally, your call to fgetpos should probably pass a pointer to an existing fpos_t (eg. using the &address-of operator). Your code currently passes a pointer to gibberish.
fgetc returns an int, so that it can represent every possible unsigned char value distinct from negative EOF values.
Suppose your char defaults to an unsigned type. (ch = fgetc(input)) converts the (possibly negative, corresponding to errors) return value straight to your unsigned char type. Can (unsigned char) EOF ever compare equal to EOF? When does your loop end?
Suppose your char defaults, instead, to a signed type. (c = fgetc(input)) is likely to turn the higher range of any returned unsigned char values into negative numbers (though, technically, this statement invokes undefined behaviour). Wouldn't your loop end prematurely (eg. before EOF), in some cases?
The answer to both of these questions indicates that you're handing the return value of fgetc incorrectly. Store it in an int!
Perhaps your loop should look something like:
for (;;) {
fpos_t p;
/* TODO: Handle fgetpos failure */
assert(fgetpos(input, &p) == 0);
int c = fgetc(input);
/* TODO: Handle fgetc failure */
assert(c >= 0);
/* TODO: Handle fsetpos failure */
assert(fsetpos(input, &p) == 0);
/* TODO: Handle fputc failure */
assert(fputc(c + 1, input) != EOF);
/* TODO: Handle fflush failure (Thank Kirilenko for this one) */
assert(fflush(input) == 0);
}
Make sure you check return values...
The update mode('+') can be a little bit tricky to handle. Maybe You could just change approach and load the whole file into char array, iterate over it and then eventually write the whole thing to an emptied input file? No stream issues.
I am completely new to C and need help with this badly.
Im reading a file with fopen(), then obtaining the contents of it using fgetc(). What I want to know is how I can access the line fgetc() returns so if I can put the 4th - 8th characters into a char array. Below is an example I found online but am having a hard time parsing the data returns, I still don't have a firm understanding of C and don't get how an int can be used to store a line of characters.
FILE *fr;
fr = fopen("elapsed.txt", "r");
int n = fgetc(fr);
while(n!= EOF){
printf("%c", n);
n = fgetc(fr);
} printf("\n");
Here
1 first open the file
2 get size of file
3 allocated size to character pointer
4 and read data from file
FILE *fr;
char *message;
fr = fopen("elapsed.txt", "r");
/*create variable of stat*/
struct stat stp = { 0 };
/*These functions return information about a file. No permissions are required on the file itself*/
stat("elapsed.txt", &stp);
/*determine the size of data which is in file*/
int filesize = stp.st_size;
/*allocates the address to the message pointer and allocates memory*/
message = (char *) malloc(sizeof(char) * filesize);
if (fread(message, 1, filesize - 1, fr) == -1) {
printf("\nerror in reading\n");
/**close the read file*/
fclose(fr);
/*free input string*/
free(message);
}
printf("\n\tEntered Message for Encode is = %s", message);
PS Dont Forget to Add #include <sys/stat.h>.
You're not retrieving a line with fgetc. You are retrieving one character at a time from the file. That sample keeps retrieving characters until the EOF character is encountred (end of file). Look at this description of fgetc.
http://www.cplusplus.com/reference/clibrary/cstdio/fgetc/
On each iteration of the while loop, fgetc will retrieve a single character and place it into the variable "n". Something that can help you with "characters" in C is to just think of it as one byte, instead of an actual character. What you're not understanding here is that an int is 4 bytes and the character is 1 byte, but both can store the same bit pattern for the same ASCII character. The only different is the size of the variable internally.
The sample you have above shows a printf with "%c", which means to take the value in "n" and treat it like an ASCII character.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
You can use a counter in the while loop to keep track of your position to find the 4th and 8th value from the file. You should also think about what happens if the input file is smaller than your maximum size.
Hope that helps.
Ok look at it as box sizes I could have a 30cm x 30cm box that can hold 1 foam letter that I have. Now the function I am calling a function that 'could' return a 60cm x 60cm letter but it 99% likely to return a 30cm x 30cm letter because I know what its reading - I know if I give it a 60cm x 60cm box the result will always fit without surprises.
But if I am sure that the result will always be a 30cm x 30cm box then I know I can convert the result of a function that returns aa 60cm x 60cm box without losing anything
Here is the snippet of code
typedef struct
{
double testA;
double testB[500];
bool isProcessed;
} MYSTURCT;
I have a binary file which is written with multiple structs of type "myStruct".
Now, in another function, I m trying to read the file and update in the middle.
void test()
{
FILE* fp = fopen (testFile, "r+")
MYSTURCT* myPtr = malloc (sizeof (MYSTRUCT));
while ( fread (myPtr,sizeof(MYSTRUCT),1,fp) )
{
if (!myPtr->isProcessed)
{
//update some thing int he struct
myPtr->testA = 100.00;
fseek (fp, -sizeof(MYSTRUCT), SEEK_CUR);
fwrite (myPtr,sizeof(MYSTRUCT), 1,fp);
}
}
}
Once I find something unprocessed, I update the struct in the memory, then try to
write the struct to the disk. (first by seeking the CURR - sizeof(struct)) position
and then fwriting the struct to disk.
Whats happening in my application is after doing the fseek, my
fp->_ptr is getting messed up and it looses the track of position in my stream.
Is there anything wrong that I am doing here?
-sizeof(STRUCT) is potentially dangerous. sizeof(STRUCT) is an unsigned type, and if it is as least as wide as an int it's promoted type (the type of the -sizeof(STRUCT) expression) will also be unsigned and have a value of about UINT_MAX - sizeof(STRUCT) + 1 or possibly ULONG_MAX - sizeof(STRUCT)+ 1.
If you're unlucky (e.g. 32 bit size_t, 64 bit long) its UINT_MAX - sizeof(STRUCT) + 1 and a long int may be able to hold this large postive value and the seek won't do what you want it to do.
You could consider doing a position save and restore:
fpos_t pos;
if (fgetpos(fp, &pos) != 0)
{
/* position save failed */
return;
}
/* read struct */
if (fsetpos(fp, &pos) != 0)
{
/* position restore failed */
return;
}
/* write struct */
fgetpos and fsetpos use a fpos_t so can potentially work with very large files in scenarios where fseek and ftell won't.
The fopen manpage says:
Reads and writes may be intermixed on
read/write streams in any order.
Note that ANSI C requires that a file positioning function
intervene
between output and input, unless an input operation encounters
end-of-
file. (If this condition is not met, then a read is allowed to
return
the result of writes other than the most recent.) Therefore it is
good
practice (and indeed sometimes necessary under Linux)
to put an
fseek(3) or fgetpos(3) operation between write and read
operations on
such a stream. This operation may be an apparent
no-op (as in
fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect.
So you might try putting the dummy fseek in right after you fwrite.
You malloc sizeof (MYSTRUCT) bytes to myPtr, but myPtr is of type MYSTURCT.
I don't think that's your problem, though.
Apparently there's nothing wrong with your code; try to add some error-checking ...
void test(){
FILE* fp = fopen (testFile, "r+"); /* missing semicolon */
MYSTURCT* myPtr = malloc (sizeof *myPtr);
while ( fread (myPtr,sizeof *myPtr,1,fp) == 1) /* error checking */
{
if (!myPtr->isProcessed)
{
//update some thing int he struct
myPtr->testA = 100.00;
if (fseek (fp, -sizeof *myPtr, SEEK_CUR) == -1)
{
perror("fseek");
}
if (fwrite (myPtr,sizeof *myPtr, 1,fp) != 1)
{
perror("fwrite");
}
}
}
}
And the fopen should be in binary mode, even if you're on Linux (where it really doesn't matter). On Windows a sequence of 0x0D 0x0A in the middle of one of those doubles will get converted to 0x0D and mess everything up.
Try fflush after the last fwrite(). Then Try making a new test file using your current structure. It could be that you changed your structure and your current test file has an older invalid byte order.
I tried your sample code, and it seems to work fine to me (though I am doing it in C - I substituted a "char" for your "boolean")
For debugging, how do you know that the fp is getting corrupted? It is unusual to look at the members of the FILE struct. Each time you do an fseek(), fread() or fwrite(), what is your output when you invoke ftell()?
if you wanted to write to the file you should use "w+b" not "r+" otherwise fwrite would fail and return the error code instead. (I think).
I'm stuck with an apparently harmless piece of code. I'm trying to read a whole flv video file into a uint8_t array, but by no reason only the 10 first bytes are read.
contents = malloc(size + 1);
if (read(fd, contents, size) < 0)
{
free(contents);
log_message(WARNING, __func__, EMSG_READFILE);
return (NULL);
}
I've tried with fopen and "rb" also, but seems that Glibc ignores that extra 'b' or something. Any clues?
Thanks in advance.
Edit: Maybe it reads a EOF character?
PS. 'size' is a variable containing the actual file size using stat().
It seems the original code correctly reads the entire content.
The problem seems to be in making use of that binary data - printing it out will truncate at the first null, making it appear that only 10 bytes are present.
You can't use any methods intended for strings or character arrays to output binary data, as they will truncate at the first null byte, making it appear the array is shorter than it really is.
Check out some other questions related to viewing hex data:
how do I print an unsigned char as hex in c++ using ostream?
Converting binary data to printable hex
If you want to append this to a string - in what format? hex? base64? Raw bytes won't work.
Here's the original code I posted. A few minor improvements, plus some better diagnostic code:
int ret, size = 4096; /* Probably needs to be much bigger */
uint8_t *contents;
contents = malloc(size + 1);
if(contents == NULL)
{
log_message(WARNING, __func__, EMSG_MEMORY);
return (NULL);
}
ret = read(fd, contents, size);
if(ret < 0)
{
/* Error reading file */
free(contents);
log_message(WARNING, __func__, EMSG_READFILE);
return (NULL);
}
for(i = 0;i < ret;++i)
{
printf("%c", contents[i]);
/* printf("%0.2X", (char) contents[i]); /* Alternatively, print in hex */
}
Now, is ret really 10? Or do you just get 10 bytes when you try to print the output?
The 'read()' function in the C library doesn't necessarily return the whole read in one shot. In fact, if you're reading very much data at all, it usually doesn't give it to you in a single call.
The solution to this is to call read() in a loop, continuing to ask for more data until you've got it all, or until read returns an error, indicated by a negative return value, or end-of-file, indicated by a zero return value.
Something like the following (untested):
contents = malloc(size + 1);
bytesread = 0;
pos = 0;
while (pos < size && (bytesread = read(fd, contents + pos, size - pos)) > 0)
{
pos += bytesread;
}
if (bytesread < 0)
{
free(contents);
log_message(WARNING, __func__, EMSG_READFILE);
return (NULL);
}
/* Go on to use 'contents' now, since it's been filled. Should probably
check that pos == size to make sure the file was the size you expected. */
Note that most C programmers would do this a little differently, probably making 'pos' a pointer which gets moved along, rather than offsetting from 'contents' each time through the loop. But I thought this approach might be clearer.
On success, read() returns the number of bytes read (which may be less than what you asked for, at which point you should ask for the rest.) On EOF it will return 0 and on error it will return -1. There are some errors for which you might want to consider re-issuing the read (eg. EINTR which happens when you get a signal during a read.)