Output random number to file in linux in C - c

I'm trying to write a number (randomly generated) to a file using a loop for some number of iterations. I have:
while (i++ < number) {
n = randno();
write(openFd, (char) n, sizeof(int));
}
The code compiles and runs. I can print 'n' to the screen, a file has been opened (code not shown), but there does not seem to be any data in the file when I try to open it using gedit. I want a file with one very large number of a certain length. Where am I going wrong? Any help is appreciated.
By the way, what is a true random function? Thank you.

The prototype for write() is:
ssize_t write(int fd, const void *buf, size_t count);
Notice the second arg is a pointer value, so it is a little bit surprising that passing that a random number there (which is what you have done1) does not seg fault.
Anyway, if what you want to do is do is write the number as text, you need to put it into a string first:
int n = randno();
char buffer[16]; // Will hold any int value + `\0`
sprintf(buffer, "%d", n);
You can now use buffer with write:
write(openFd, buffer, strlen(buffer));
1. n is an int; casting it with (char) simply truncates it. Perhaps you meant (char*)&n, which will work to write out the number, but in binary, not text! I presume that's not what you want since you were examining the file in gedit.

You could also use fprintf if you have a FILE*
fprintf(fp, "%d",n);

By casting n to a char type you have created something that will randomly write the memory pointed to from a number between 0 to 255. Expanding what you are doing, all you would need is.
while (i++ < number) {
int n;
n = randno();
write(openFd, &n, sizeof(int));
}
The & operator will pass a pointer to N instead of the n value...

A true random function is something that output real random numbers that are not computable.
/dev/random on linux as opposed to /dev/urandom.
For your file-write I would use ''fprintf''

Related

Codification, write an integer in a file

I am doing a coding task in the C language, I go well until the part of reading the symbol and assign the corresponding code according to a table. I must concatenate several codes until they reach 32 bits in length, to accomplish this I must write them in a file.
This method of writing to file is giving me a lot of problems, I'm trying to do it with the fputc() function.
I can not change the declaration of the function because they request it for the homework.
I create a mask to be able to write the integer by bytes because they also suggest that the teachers of the course.
The program with that code works but when I see the file with a binary viewer it only prints zero.
Any idea of what I'm doing wrong?
Thanks!
void write_int(FILE* fp, unsigned int buffer, int nbytes){
if ( (nbytes <= sizeof(int)) && (nbytes>=0) ){
unsigned int aux;
int i;
for (i=4; i>(4-nbytes) ; i--){
aux = buffer & new_mask( ((i*8)-1),((i-1)*8));
fputc(aux,fp)
}
fputc('\n',fp);
}else{
printf("nbytes out of range");
}
}
fputc is used to write one ASCII-character into a file.
int fputc(int, FILE*) //this int is converted to unsigned before going to the file(your bits are probably being messed up here)
1- solution: Open this file in binary mode and write using fwrite
fp = fopen("filename", "wb+");
fwrite(buffer, 4, 1, fp);
*since integers on most computers have 32bits(4bytes) this should write your whole 32 bits at once in a binary file
2- solution: Assuming that you can't open the file in binary mode inside this function... you could simply write 4chars usgin fprintf.
int fprintf(FILE*, format, ....);
*note: it's hard to help more than this, because it's not clear what is nature of these symbols.
ex: binary stream, integer number, ascii, utf, etc

For loop doesn't stop on the strlen

My biggest problem is on this line:
for(i=0;i<=strlen(enc);i++) ->
7th line of the function decifrar:
It keeps the loop even with the memset used to clear the memory (it's even bigger than the string length)
Note if I use the actual length of the string in that line the code does works (i.e. replacing strlen(enc) with 60 )
void decipher(int k, char *enc){
char alfa[]="9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA";
char *pch;
int i;
for(i=0;i<=strlen(enc);i++){
pch=strchr(alfa, enc[i]);
if (pch) enc[i] = *(pch + k),enc[i]=tolower(enc[i]);
}
printf("%s",enc);
}
int main(){
int keys[6]={1,4,15,24,12,20},i;
char *txt="rfgr r hz grkgb fvzcyrf dhr cergraqr fre grfgnqb ab cebtenzn";
char *txttemp=malloc(sizeof(char)*1024);
for(i=0;i<6;i++){
printf("\n\n\t Attempt number: %d\n\n",i+1);
memset(txttemp,'\0',sizeof(char)*strlen(txt)+30);
memcpy(txttemp, txt, strlen(txt));
decipher(keys[i],txttemp);
}
return 0;
}
What is the point that I am missing? Is the usage of strlen wrong?
It's < not <= in the for-loop.
But as a Note: avoid that pattern. Strlen means you count the length of the string, but you probably should already know it from somewhere (i.e. when you receive it: the file length, the number of charecters returned etc...). Save it and take that value as the length. This is the source of a lot of security holes in programs (a buffer overflow).
std::string has this as a built-in functionality and it's what I would recommend over a plain char* almost all of the time (that is if you can use C++)

Simple count how many integers are in file in C

Im currently learning C through random maths questions and have hit a wall. Im trying to read in 1000 digits to an array. But without specifiying the size of an array first i cant do that.
My Answer was to count how many integers there are in the file then set that as the size of the array.
However my program returns 4200396 instead of 1000 like i hoped.
Not sure whats going on.
my code: EDIT
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE* fp;
const char filename[] = "test.txt";
char ch;
int count = 0;
fp = fopen(filename, "r");
if( fp == NULL )
{
printf( "Cannot open file: %s\n", filename);
exit(8);
}
do
{
ch = fgetc (fp);
count++;
}while (ch != EOF);
fclose(fp);
printf("Text file contains: %d\n", count);
return EXIT_SUCCESS;
}
test.txt file:
731671765313306249192251196744265747423553491949349698352031277450632623957831801698480186947885184385861560789112949495459501737958331952853208805511
125406987471585238630507156932909632952274430435576689664895044524452316173185640309871112172238311362229893423380308135336276614282806444486645238749
303589072962904915604407723907138105158593079608667017242712188399879790879227492190169972088809377665727333001053367881220235421809751254540594752243
525849077116705560136048395864467063244157221553975369781797784617406495514929086256932197846862248283972241375657056057490261407972968652414535100474
821663704844031998900088952434506585412275886668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912883142607690042
242190226710556263211111093705442175069416589604080719840385096245544436298123098787992724428490918884580156166097919133875499200524063689912560717606
0588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
Any help would be great.
You forgot to initialize count, so it contains random garbage.
int count = 0;
(But note that with this change it's still not going to work, since %d in a scanf format means read as many digits as you find rather than read a single digit.)
Turn on your compiler's warnings (-Wall), it will tell you that you didn't initialize count, which is a problem: it could contain absolutely anything when your program starts.
So initialize it:
int count = 0;
The other problem is that the scanfs won't do what you want, at all. %d will match a series of digits (a number), not an individual digit. If you do want to do your counting like that, use %c to read individual characters.
Another approach typically used (as long as you know the file isn't being updated) is to use fseek/ftell to seek to the end of the file, get the position (wich will tell you its size), then seek back to the start.
The fastest approach though would be to use stat or fstat to get the file size information from the filesystem.
If you want number of digits thin you tave to do it char-by-char e.g:
while (isdigit(fgetc(file_decriptor))
count++;
Look up fgetc, getc and scanf in manpages, you don't seem to understand whats going on in your code.
The way C initializes values is not specified. Most of the time it's garbage. Your count variable it's not initialized, so it mostly have a huge value like 1243435, try int count = 0.

Combing two files with binary format

I wrote this code to test to combine two files:
long getFileSize(char *filename)
{
FILE* fp=fopen(filename,"rb");
fseek(fp,0,SEEK_END);
long size=ftell(fp);
fclose(fp);
return size;
}
long lengthA = getFileSize(argv[1]);
long lengthB = getFileSize(argv[2]);
printf("sizeof %s is:%d\n",argv[1],lengthA);
printf("sizeof %s is %d\n",argv[2],lengthB);
void *pa;
void *pb;
FILE* fp=fopen(argv[1],"rb");
fread(pa,1,lengthA,fp);
fclose(fp);
FILE* fpn=fopen(argv[2],"rb");
fread(pb,1,lengthB,fpn);
fclose(fpn);
printf("pointerA is:%p;pointerB is:%p\n",pa,pb);
FILE *ff=fopen("test.pack","wb");
fwrite(pa,1,lengthA,ff);
fwrite(pb,1,lengthB,ff);
fclose(ff);
long lengthFinal = getFileSize("test.pack");
printf("Final size:%i\n",lengthFinal);
however I don't know if the data is equal to the returned value from getFileSize,the console print clearly says something wrong with it,but I can't figure it out:
sizeof a.zip is:465235
sizeof b.zip is 107814
pointerA is:0x80484ec;pointerB is:0x804aff4
Final size:255270
since I know the length of each file,I can then use fseek to restore them right? that's the idea I was thinking.
*pa and *pb need to point to some memory where the file content shall be read to.
So, do a malloc for these two buffers with lengthA*sizeof(char) and lengthB*sizeof(char) and pass these allocated buffers to fread:
pa = malloc(lengthA*sizeof(char));
pb = malloc(lengthB*sizeof(char));
...
fread(pa,sizeof(char),lengthA,fp);
...
fread(pb,sizeof(char),lengthB,fpn);
Furthermore, fread returns the number of items actually read. Also check this!
Excerpt from man fread:
fread() and fwrite() return the number of items successfully read or written (i.e., not the number of characters). If an error occurs, or the end-of-file is reached, the return value is a short item count (or zero).
Note that there's no real reason to load both source files into memory at once. Also, it's potentially very memory-inefficient to do so, since you're really reading all of the files in, and then all you do is write the contents out again.
A better algorithm, in my opinion, would be:
let C = a reasonable buffer size, say 128 KB
let B = a static buffer of C bytes
let R = the output file, opened for binary write
for each input file F:
open F for binary read
repeat
let N be the number of bytes read, up to a maximum of C
if N > 0
write N first bytes of B into R
until N = 0
close F
close R
This does away with the need to allocate buffers dynamically, you could just do char C[B] and have #define B (128 << 10).
The above assumes that reading from a file which has no more bytes to deliver returns 0 bytes.
Also note that by doing away with the need to load the entire file, you also no longer need to open each input file an extra time just to seek to the end in order to compute the file's size.
pa and pb are not pointing to valid memory.
char* pa = malloc(lengthA * sizeof(char));
char* pb = malloc(lengthB * sizeof(char));
Remember to free() when no longer required.
Check all return values from functions fopen(), fread(), fwrite(), etc.

Segfault in fread()

I'm trying to read a BMP image (greyscales) with C, save values into an array, and convert this array to a string with values separated with a comma.
My program worked well under Windows 7 64-bit, but I had to move to Windows XP 32-bit because of library compatibility problems.
I have 1,750 images to read, and I want to store all of them in a single string.
When I launch my program it goes fine until the 509:th image, then I get a Segmentation Fault caused by fread(). Here's my code:
int i=0,j,k,num,len,length,l;
unsigned char *Buffer;
FILE *fp;
char *string,*finalstring;
char *query;
char tmp2[5],tmp[3];
query = (char *)malloc(sizeof(char)*200000000);
string = (char *)malloc(sizeof(char)*101376);
Buffer = (unsigned char *)malloc(sizeof(unsigned char)*26368);
BITMAPFILEHEADER bMapFileHeader;
BITMAPINFOHEADER bMapInfoHeader;
length = 0;
for (k =1;k<1751;k++)
{
strcpy(link,"imagepath");
//here just indexing the images from 0000 to 1750
sprintf(tmp2,"%.4d",k);
strcat(link,tmp2);
strcat(link,".bmp");
fp = fopen(link, "rb");
num = fread(&bMapFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
num = fread(&bMapInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);
//seek beginning of data in bitmap
fseek(fp,54,SEEK_SET);
//read in bitmap file to data
fread(Buffer,26368,1,fp);
l=0;
for(i=1024;i<26368;i++)
{
itoa(Buffer[i],tmp,10);
len = strlen(tmp);
memcpy(string+l,tmp,len);
memcpy(string+l+len,",",1);
l = l+len+1;
}
memcpy(query,"",1);
memcpy(string,"",1);
printf("%i\n",k);
}
Thanks
Make it tmp[4]; for three digits and the terminating 0.
Also: where is the fclose? I suspect that you're running out of file handles.
Check, whether fp != 0.
Where did you get 101376 from? Each of your bytes take up at most 5 characters as a decimal number with comma (e.g. -127,), 5*26368 is 131840.
Get rid of the casts in malloc calls. And #include <stdlib.h>.
What's the output of this program, in both the 64-bit and 32-bit systems you're using?
#include <stdio.h>
int main(void) {
printf("sizeof (int) is %d\n", (int)(sizeof (int)));
printf("sizeof (int*) is %d\n", (int)(sizeof (int*)));
return 0;
}
Run your program in the debugger.
Set a breakpoint at the call to
fread -- make it conditional on
k==507 (this will stop it when you
expect the fread to be successful).
When the program hits the
breakpoint, examine the variables
and check what is about to be passed
to fread. The first one or two times
you hit the breakpoint, the values
will be good.
Then on the 509th time, you will
probably see bogus values being passed
to fread. Figure out where those
bogus values are coming from --
possibly set a conditional
breakpoint on the variable being set
to whatever the bogus value is.

Resources