#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd, offset;
char *data;
struct stat sbuf;
int counter;
if (argc != 2) {
fprintf(stderr, "usage: mmapdemo offset\n");
exit(1);
}
if ((fd = open("mmapdemo.c", O_RDONLY)) == -1) {
perror("open");
exit(1);
}
if (stat("mmapdemo.c", &sbuf) == -1) {
perror("stat");
exit(1);
}
offset = atoi(argv[1]);
if (offset < 0 || offset > sbuf.st_size-1) {
fprintf(stderr, "mmapdemo: offset must be in the range 0-%ld\n",sbuf.st_size-1);
exit(1);
}
data = mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (data == (caddr_t)(-1)) {
perror("mmap");
exit(1);
}
// print the while file byte by byte
while(counter<=sbuf.st_size)
printf("%c", data++);
return 0;
}
This gives me error as follows:
gcc mmapdemo.c -o mmapdemo
mmapdemo.c: In function 'main':
mmapdemo.c:48: warning: format '%c' expects type 'int', but argument 2 has type 'char *'
Please help me to solve the problem.
printf("%c", *data++);
data is a char *. The %c format specifier tells printf to expect a char. To get a char from a char *, you need to dereference the pointer using the * operator.
That said, your program still won't work properly because you're not incrementing counter in your print loop, nor have you initialized it. I would go with:
for (size_t i = 0; i < sbuf.st_size; ++i) {
printf("%c", data[i]);
}
instead. I haven't inspected the rest of your program, but given that there were three serious errors in three lines that I looked at, I doubt that the rest is bug-free.
to print it out byte by byte, need to use
printf("%c ", *data++)
or to print out the hex values:
printf("%02X", *data++);
Related
I'm following a tutorial from BeeJ's website and i've learnt quite a bit of it.
I'm in that stage of experimentation and want to somehow build upon this code.
In short, say the user types an address: 1050576 for a file that's roughly 1000MB, the program (shown below) should map the chunk in the file data up to a position where 1050576 falls between chunk beginning and its length.
When i run the code, it says the max address size is 924 and so i can't really chunk a file that's 1000mb.
Could someone help explain / provide an example on how i can tackle this?
/*
** mmapdemo.c -- demonstrates memory mapped files lamely.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd, offset;
char *data;
struct stat sbuf;
if (argc != 2) {
fprintf(stderr, "usage: mmapdemo offset\n");
exit(1);
}
if ((fd = open("mmapdemo.c", O_RDONLY)) == -1) {
perror("open");
exit(1);
}
if (stat("mmapdemo.c", &sbuf) == -1) {
perror("stat");
exit(1);
}
offset = atoi(argv[1]);
if (offset < 0 || offset > sbuf.st_size-1) {
fprintf(stderr, "mmapdemo: offset must be in the range 0-%ld\n", sbuf.st_size-1);
exit(1);
}
if ((data = mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t)(-1)) {
perror("mmap");
exit(1);
}
printf("byte at offset %d is '%c'\n", offset, data[offset]);
return 0;
}
Programming Language C
below is the code that uses multiple threads to print out a file. There are no errors, however the code doesn't work correctly. However, when compiled it shows this warning 5 times:
'cast from pointer to integer of different size'
I've tried everything I can think of to resolve this issue, but haven't been success and now are just shooting in the dark. Does anyone see where my mistake is? Any help is greatly appreciated and will gladly provide any other information upon request.
Thanks.
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#define NUM_THREAD 4
struct fileParams {
int fd;
int size;
};
void *printFile(void *stuff)
{
struct fileParams *params = stuff;
int addr;
addr=(unsigned char *)mmap(NULL, (int) ¶ms->size, PROT_READ,
MAP_PRIVATE,(int) ¶ms->fd,0);
write(STDOUT_FILENO, addr, (int)¶ms->size);
}
int main (int argc, char * argv[])
{
pthread_t threads[NUM_THREAD];
unsigned char *addr;
int fd,rc;
struct stat sb;
int numCPU=sysconf(_SC_NPROCESSORS_ONLN);
struct fileParams params;
printf("Number of aviable cores: %d\n",numCPU);
printf("Using 4 processors\n");
if (argc != 2 || strcmp(argv[1], "—help") == 0)
printf("Usage: %s file\n", argv[0]);
fd=open(argv[1],O_RDONLY);
if (fd == -1)
{
printf("File open fdailed.\n");
exit(EXIT_FAILURE);
}
if (fstat(fd, &sb) == -1)
{
printf ("fstat error\n");
exit(EXIT_FAILURE);
}
params.fd=fd;
params.size=sb.st_size/4;
for (int n = 0; n<4; n++)
rc=pthread_create(&threads[n],NULL,printFile,¶ms);
exit(EXIT_SUCCESS);
}
You need provide inputs to functions that match the function - passing pointers where integers are wanted (or the other way around) will generate warnings or errors depending on compile options.
mmap takes an size_t as the 2nd parameter, but you are giving it a cast int to a pointer (¶ms->size), the same with mmaps 5th parameter.
Get rid of the '&' so it is just a int.
mmap also returns a void *, which you are then assigning to addr (an int).
Change int to a void * pointer type which should also fix the 5th warning.
So I want to make a file named genData.c that when executed for example: ./genData filename.txt will write 1 character to that file 1000 times.
In essence creating a 1kb file.
I would like to be able to modify the for loop, say 100000 times, to generate a 1MB file and so on.
Here is what I have tried and it compiles but when executed causes a segmentation fault.
Any suggestions? Sorry C is a language I've never dabbled in.
#include <stdio.h>
int main (int argc, char *argv) {
char ch = 'A';
FILE *fp;
fp = fopen(argv[1], "wb");
int i;
for (i = 0; i < 1000; i++) {
fwrite(&ch, sizeof(char), 1, fp);
}
fclose(fp);
return 0;
}
If you compile with warnings, you get a hint as to the exact problem:
test.c:3:5: warning: second argument of ‘main’ should be ‘char **’ [-Wmain]
int main (int argc, char *argv) {
^
All your troubles start downstream of this error. Fix this argument, and your code will work.
In the future, get into the habit of compiling with warnings turned on:
$ gcc -Wall foo.c
...
This will help catch typos and other oddities that will cause problems.
Since you tagged it Linux, this is how you can do it with the system-level functions (this should be a correct, most efficient way to do it):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <fcntl.h>
#include <string.h>
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, const void *ptr, size_t n);
int
main (int argc, char** argv) {
char buf[1000];
memset(buf, 'A', sizeof(buf));
int fd;
if((fd = open(argv[1], O_WRONLY|O_CREAT, 0666))<0){
perror(argv[1]);
exit(EX_NOPERM);
}
ssize_t left = writen(fd, buf, sizeof(buf));
if(left)
perror("write error\n");
return !!left;
}
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, const void *ptr, size_t n) {
size_t nleft;
ssize_t nwritten;
nleft = n;
while (nleft > 0) {
if ((nwritten = write(fd, ptr, nleft)) < 0) {
if (nleft == n)
return(-1); /* error, return -1 */
else
break; /* error, return amount written so far */
} else if (nwritten == 0) {
break;
}
nleft -= nwritten;
ptr += nwritten;
}
return(n - nleft); /* return >= 0 */
}
#include <stdio.h>
#include <stdlib.h>
#define SIZE_OF_FILE 1024
int main(int argc, char *argv[])
{
FILE *fdest;
char ch = '\n';
if(argc != 2)
exit(EXIT_FAILURE);
fdest = fopen(argv[1], "wb");
if (fdest == NULL)
exit(EXIT_FAILURE);
fseek(fdest, SIZE_OF_FILE - 1, SEEK_CUR);
fwrite(&ch, sizeof(char), 1, fdest);
fclose(fdest);
return 0;
}
In essence creating a 1kb file
if the only purpose is creating a file with sizeof x, it is more simple i belive.
I have a piece of code to create function to print a message from input parameter.
I've been compiling the code with c9.io and works pretty well without warnings but when i do it locally it shows a warning like this:
child2bok: c39:11: warning: Ignoring return value of 'write', declares with attribute warn_unused_result [-Wunused -result]
And this is the code.Sure it is a problem with write() definition but i'm so novice with unix programming and no idea to solve it. It executes well but i'd like to remove the warning before i deliver to the teacher.
Here you are the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>
#include "rutines.h"
void children();
void show_help();
int main(int argc, char *argv[])
{
int ord;
if (argc > 1)
ord = atoi(argv[1]);
if (argc == 1)
{
show_help("Error");
exit(1);
}
children(ord);
}
void children(int ord)
{
char msg[10];
srand(getpid());
sleep(rand() % 5);
sprintf(msg, " %d", ord);
while (strlen(msg) > 0)
{
int written= write(1, msg, strlen(msg));
if (written < 0)
break;
exit(0);
}
void show_help(char *err_message)
{
write_string(err_message,"");
write_string("Usage: child2aok \n","");
}
You should check and handle the value returned by the write() command. From the write documentation:
write [...] may return less than count even under valid conditions.
Why don't you simply use printf(" %d", ord); instead of sprintf(msg, " %d", ord); write(1, msg, strlen(msg))?
write does not guarantee to write all the data; it may write as little as one byte (or block, or return an error, ...). So you have to use it in a loop:
bool write_all(int fd, void * buf, size_t len)
{
size_t remaining = len;
for (size_t n; (n = write(fd, buf, remaining)) > 0; remaining -= n)
{ }
return remaining == 0;
}
This function returns true if all bytes were written, and false on error.
I am working on a project that uses non standard C Libraries to display the output on an LCD screen. I have the code working great but I have run into a problem.
What my intended purpose of this program is to do is take a command line string of text and convert it to the ASCII decimal values then display them on the screen. The way that you output text to the screen is by making a call to the serialPutchar function so to display the letter H I would write it as serialPutchar(fd, 'H'); I want to be able to get the values from variables and output the letters in the variable.
The problem is that when I write it as serialPutchar(fd, "%c", H); or try serialPutchar(fd, "%d", x); I get the following error:
testing.c: In function âmainâ:
testing.c:22:3: warning: passing argument 1 of âserialPutcharâ makes integer from pointer without a cast [enabled by default]
/usr/local/include/wiringSerial.h:30:14: note: expected âintâ but argument is of type âchar *â
testing.c:22:3: error: too many arguments to function âserialPutcharâ
/usr/local/include/wiringSerial.h:30:14: note: declared here
I'm guessing it cant be used in that fashion like you would use printf so is there an alternative to this or maybe I just have a simple error I am not spotting. I am including a link to the documentation for the wiringSerial library. Also from my error output I am getting the strange characters around the error testing.c In function main: and several other lines. Is there a way to prevent this? Link to library HERE Below is my working code to output HELLO:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <wiringPi.h>
#include <wiringSerial.h>
int main (int argc, char *argv[])
{
int fd ;
if ((fd = serialOpen ("/dev/ttyAMA0", 9600)) < 0)
{
fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
return 1 ;
}
if (wiringPiSetup () == -1)
{
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
return 1 ;
}
int H = 1;
serialPutchar(fd, 'H');
serialPutchar(fd, 'E');
serialPutchar(fd, 'L');
serialPutchar (fd, 'L');
serialPutchar (fd, 'O');
}
:::UPDATE:::
Here is the working code that fit my description:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <wiringPi.h>
#include <wiringSerial.h>
int main (int argc, char *argv[])
{
int fd ;
if ((fd = serialOpen ("/dev/ttyAMA0", 9600)) < 0)
{
fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
return 1 ;
}
if (wiringPiSetup () == -1)
{
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
return 1 ;
}
for (int i=1; i<argc; i++){
serialPrintf (fd, "%s", argv[i]);
}
}
putChar takes a char as its second argument. Not a string, not a format string with arguments, just a char.
If you have a char in a variable x, just do:
serialPutchar(fd, x);