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);
Related
I'm new to C and stackoverflow, so pardon me if my question is silly or a duplicate.
So i tried to read some lines of string (and integers) from a .txt files and store it into an array of tuples. The strings read from the file seems to contain '\n' everytime, so i use strcspn() to remove it.
FILE* f = fopen("board.txt","r");
int x;
size_t size = 30;
char *buffer;
for (i=1;i<=32;i++)
{
buffer = (char *)malloc(size);
x = getline(&buffer,&size,f);
buffer[strcspn(buffer,"\n")] = 0;
A[i].name = buffer;
buffer = (char *)malloc(size);
x = getline(&buffer,&size,f);
buffer[strcspn(buffer,"\n")] = 0;
A[i].type = buffer;
buffer = (char *)malloc(size);
x = getline(&buffer,&size,f);
A[i].price = atoi(buffer);
}
for (i=1;i<=32;i++)
printf("%s ",A[i].name);
for (i=1;i<=32;i++)
printf("%s ",A[i].type);
However, when i tried the code above, the printf failed to print anything. But then when i tried to use \n in the printf ( printf("%s\n",A[i].type); ) it worked just fine. It seems like the strings completely disappear when i remove the "\n", and then come back only when i put '\n' as i print it.
Can someone explain what is wrong in the code? Or is it a library problem? Thank you in advance.
Edit : So to explain it a little further, i need those string (name and type) to be printed into 'boxes' to form a kind of board game, so i think bringing newline would cause a lot of trouble later on.
This is the correct behavior. The '\n' causes the OS to flush the buffer used for prints, so that it appears on stdout. Without a '\n' the OS isn't forced to write your print to stdout yet.
printf belongs to the Standard I/O library, it is a line buffered function. So when this function is called, it stores characters in a buffer and the only way to get the output (to stdout) is to flush with a newline character. This is the way it was designed so as to maintain a minimal number of system calls as possible.
Try eliminating this,
buffer[strcspn(buffer,"\n")] = 0;
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
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
The Problem was to find and replace a string in a C File.
I am new to C Files. I have tried the following code but I didnt get any output:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *f1,*f2;
char *src,*dest,*s1,ch,ch1,ch2,ch3;
int i;
f1=fopen("input.txt","rw");
f2=fopen("dummy.txt","rw");
src="mor";
dest="even";
while(ch!=EOF)
{
ch=fgetc(f1);
if(ch==src[0]) //Finding 1st char of src
{
fgets(s1,strlen(src),f1);
if(strcmp(src+1,s1)==0) //Finding occurance of "src" in file
{
fseek(f1,strlen(src)-1,SEEK_CUR);
while(ch1!=EOF) //Copying remaining data into another file
{
ch1=fgetc(f1);
fputc(ch1,f2);
}
fseek(f1,-strlen(src),SEEK_CUR);
for(i=0;i<strlen(dest);i++) //replacing "src" with "dest"
{
ch2=dest[i];
fputc(ch2,f1);
}
fclose(f1);
f1=fopen("input.txt","a");
while(ch3!=EOF) //Appending previosly copied data into 1st file
{
ch3=fgetc(f2);
fputc(ch3,f1);
}
}
}
}
fclose(f1);
fclose(f2);
}
The Contents of input.txt is "morning".
Kindly point the ERROR in the logic and also give an efficient code for the same.
Thanks in Advance.
Reading files in C is usually a bit messy. The first problem that I see is the way ch is used in the main loop. The first time
while (ch != EOF)
is executed, ch is uninitialized, and if it happens to hold EOF, the main loop will not execute at all. I usually use the following structure for reading from files:
FILE *fInput = fopen("input.txt", "r");
int ch; /* need an int to hold EOF */
for (;;)
{
ch = fgetc(fInput);
if (ch == EOF) break;
...
}
In addition, you may need to read up on file pointer concept. For example, after reading the remainder of src, you fseek() forward, and skip some more characters before you copy data to f2. Essentially, you read m, read or (with fgets() - and into an unallocated buffer s1 that would go ka-boom on you some time in the near future), skip 2 more characters (now your pointer is at last n of "morning"), copy "ng" into f2, try to write EOF to f2 in this loop (hence the above pattern for reading until EOF), seek two characters back (which may fail once you reach EOF, my C file functions are a bit rusty these days), write "even" to f1 (which should, if I am wrong about seek after EOF, set input file to "mornieven", and not change it if I am correct). In summary, I don't think the code does what you intend it to do.
I would recommend building up your function. Each one of the following can be written as a program that you should test and finish before going to next step:
read the file safely, and print it out
detect the contents of src, and print the rest of input
save the rest of the input to second file instead of printing
replace src with dest in first file, and ignore the rest (since you open input file with 'rw', this will truncate the rest of input). You may need to do an fseek() to clear the EOF status. Also look at ftell() to record a position that you can jump back to using fseek()
finally, copy in everything you have saved to second file after replacing src with dest (no need to close f1 here. But it is better to open f2 as write, close after copy from first file, and reopen as read to perform the copy back to f1).
In addition, when you need a buffer (such as s1), just use a large enough array for now, but look into malloc() and free() functions to perform dynamic memory allocations for situations like these.
One simple way to do the replace would be to first read in the whole file into a buffer
e.g.
FILE* fpIn = fopen("file.txt","rb");
fseek(fpIn, 0L, SEEK_END);
size_t s = ftell(fpIn);
fseek(fpIn, 0L, SEEK_SET);
void* buf = malloc(s);
fread(buf,s,1,fpIn);
now while writing the file, check for your string
char src[] = "mor";
char dest[] = "even";
int lenSrc = strlen(src);
int lenDest = strlen(dest);
for (char* ch = buf; ch < buf + s; ++ch)
{
if ( !memcmp( ch, src, lenSrc ) )
{
fwrite( dest, 1,lenDest, fpOut );
ch += lenSrc;
}
else
{
fputc( *ch, fp );
}
}
disclaimer: haven't compiled this
You are printing the wrong thing in your output. Print, "ch", not the file pointer.
while(ch!=EOF)
{
ch=getc(f1);
printf("%c",ch);
}
while(ch!=EOF)
{
ch=getc(f2);
printf("%c",ch);
}
Also, f2 is closed at the end during your output. You'll have to reopen it (just like you do with f1.)
At first glance, I see that your code to call fgets is wrong. You have not allocated any memory and you are reading a string into an uninitialized pointer. Read into an array or dynamically allocated memory.
Another problem is that you are declaring ch as char. fgetc() returns an int, and for good reason. It is good to be able to return any possible character or EOF, so EOF shouldn't be a character, so ideally fgetc() returns a bigger type than char.
The upshot is that the loop may well never end, since ch can't possibly hold EOF on some standard implementation. Declare it (and ch1 and ch3) as int.
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.)