I am seeking to a certain position in the file to get an entry count (which tells how many time to do the for loop). can i simply do it like this? i am kind of new to C so please take it easy on me Any input will be valuable. and please dont give me a working program, just tell me if the condition of the for loop would work and if it wouldnt, how i couldpossibly fix it.We can use an example of the entryCount = 40 from fread
psuedocode ofcourse:
unsigned char buffer[8]
fseek (file to position where entry count is);
entryCount = fread (buffer, sozeof(buffer), 1, in);
// cound i just fread(**entryCount**, sizeof(buffer), 1, in); ?
for ( x = 0; x < entryCount; x++ ) {
// execute code as many time is stored in "entryCount"
}
continue script ect
thanks for looking and for your valuable input
almost correct:
you need to have a int declaration for x (or whatever var)
more of a suggestion - 'i' is usually used for loop variables
for (int i = 0; i < entryCount; i++ ) {
// execute code as many time is stored in "entryCount"
}
Related
WHAT THE CODE DOES: I read a binary file and sort it. I use a frequency array in order to do so.
UPDATES:it does do the loop, but it doesn`t write the numbers correctly...
That is the code. I want to write on file after reading from it. I will suprascript what is already written, and that is okey. The problem is I have no error on compiling, but at run time it seems I have an infinite loop.
The file is binary. I read it byte by byte and that`s also the way I want to write it.
while(fread(readChar, sizeof(readChar)/2, 1, inFile)){
bit = atoi(readChar);
array[bit] = array[bit] + 1;
}
fseek(inFile, 0, SEEK_SET);
for( i = 0; i < 256; i++)
while(array[i] > 0){
writeChar[0] = array[i]; //do I correctly convert int to char?
fwite(writeChar, sizeof(readChar)/2, 1, inFile);
array[i] = array[i] -1;
}
The inFile file declaration is:
FILE* inFile = fopen (readFile, "rb+");
It reads from the file, but does not write!
Undefined behavior:
fread() is used to read a binary representation of data. atoi() takes a textual represetation of data: a string (a pointer to an array of char that is terminated with a '\0'.
Unless the data read into readChar has one of its bytes set to 0, calling atoi() may access data outside readChar.
fread(readChar, sizeof(readChar)/2, 1, inFile);
bit = atoi(readChar);
Code it not reading data "bit by bit" At #Jens comments: "The smallest unit is a byte." and that is at least 8 bits.
The only possible reason for an infinite loop I see is, that your array is not initialized.
After declaration with:
int array[256];
the elements can have any integer value, also very large ones.
So there are no infinite loops, but some loops can have very much iterations.
You should initialize your array with zeros:
int array[256]={0};
I don't know the count of elements in your array and if this is the way you declare it, but if you declare your array like shown, than ={0} will initialize all members with 0. You also can use a loop:
for(int i=0; i < COUNT_OF_ELEMENTS;i++) array[i] = 0;
EDIT: I forgot to mention, that your code is only able to sort files with only numbers within.
For that, you have also to change the conversion while writing:
char writeChar[2]={0};
for( int i = 0; i < 256; i++)
while(array[i] > 0){
_itoa(i,writeChar,10);
fwrite(writeChar, sizeof(char), 1, inFile);
array[i] = array[i] -1;
}
File content before:
12345735280735612385478504873457835489
File content after:
00112223333334444455555556777778888889
Is that what you want?
I need to make an C application for school and im stuck at one bit. I filled my struct with word from a file wich works fine, except for the time it just prints a random integer i guess?
My code:
char buffer[20];
int i;
for(i = 0; i < 10; i++) {
fgets(buffer,20,fp);
apcWordList[i].pcWord = strdup(buffer);
apcWordList[i].cMaxScore = 0;
apcWordList[i].tTime = time(NULL);
}
fclose(fp);
Now what i wanted to do was this(sSecretWord is the word the person guessed and score the points he got for guessing the word):
for(i = 0; i < 10; i++) {
fgets(buffer,20,fp);
if(apcWordList[i].pcWord == sSecretWord && score > apcWordList[i].cMaxScore) {
apcWordList[i].cMaxScore = score;
apcWordList[i].tTime = time(NULL);
}
}
but it crashes and I am really confused how to compare the variables and change them when needed. I hope I have explained it well enough and my English could be read well.
Assuming pcWord is a char *, you cannot compare that pointer using ==, most of the time.
There is no string data type in C, a string is never a single value.
You must use strcmp():
if(strcmp(apcWordList[i].pcWord, sSecretWorD) == 0 &&
score > apcWordList[i].cMaxScore)
The rest of your code makes little sense, I'm afraid. The loop has a typo, and there's no connection between the fgets() and the if. I don't think the fgets() should be in the second part of the code, at all.
The following expression in your if condition
apcWordList[i].pcWord == sSecretWord
compares the memory addresses they evaluate to and not the values stored at those memory locations which is probably what you want. You should use strcmp instead to compare the strings pointed to by above two variables.
strcmp(apcWordList[i].pcWord, sSecretWorD) == 0
I'm actually writing about the same program as before, but I feel like I've made significant progress since the last time. I have a new question however; I have a function designed to store the frequencies of letters contained within the message inside an array so I can do some comparison checks later. When I ran a test segment through the function by outputting all of my array entries to see what their values are, it seems to be storing some absurd numbers. Here's the function of issue:
void calcFreq ( float found[] )
{
char infname[15], alpha[27];
char ch;
float count = 0;
FILE *fin;
int i = 0;
while (i < 26) {
alpha[i] = 'A' + i++;
}
printf("Please input the name of the file you wish to scan:\n");
scanf("%s", infname);
fin = fopen ( infname, "r");
while ( !feof(fin) ) {
fscanf(fin, "%c", &ch);
if ( isalpha(ch) ) {
count += 1;
i = 0;
if ( islower(ch) ) { ch = toupper(ch); }
while ( i < 26 ) {
if ( ch == alpha[i] ) {
found[i]++;
i = 30;
}
i++;
}
}
}
fclose(fin);
i = 0;
while ( i < 26 ) {
found[i] = found[i] / count;
printf("%f\n", found[i]);
i++;
}
}
At like... found[5], I get this hugely absurd number stored in there. Is there anything you can see that I'm just overlooking? Also, some array values are 0 and I'm pretty certain that every character of the alphabet is being used at least once in the text files I'm using.
I feel like a moron - this program should be easy, but I keep overlooking simple mistakes that cost me a lot of time >.> Thank you so much for your help.
EDIT So... I set the entries to 0 of the frequency array and it seems to turn out okay - in a Linux environment. When I try to use an IDE from a Windows environment, the program does nothing and Windows crashes. What the heck?
Here are a few pointers besides the most important one of initializing found[], which was mentioned in other comments.
the alpha[] array complicates things, and you don't need it. See below for a modified file-read-loop that doesn't need the alpha[] array to count the letters in the file.
And strictly speaking, the expression you're using to initialize the alpha[] array:
alpha[i] = 'A' + i++;
has undefined behavior because you modify i as well as use it as an index in two different parts of the expression. The good news is that since you don't need alpha[] you can get rid of its initialization entirely.
The way you're checking for EOF is incorrect - it'll result in you acting on the last character in the file twice (since the fscanf() call that results in an EOF will not change the value of ch). feof() won't return true until after the read that occurs at the end of the file. Change your ch variable to an int type, and modify the loop that reads the file to something like:
// assumes that `ch` is declared as `int`
while ( (ch = fgetc(fin)) != EOF ) {
if ( isalpha(ch) ) {
count += 1;
ch = toupper(ch);
// the following line is technically non-portable,
// but works for ASCII targets.
// I assume this will work for you because the way you
// initialized the `alpha[]` array assumed that `A`..`Z`
// were consecutive.
int index = ch - 'A';
found[index] += 1;
}
}
alpha[i] = 'A' + i++;
This is undefined behavior in C. Anything can happen when you do this, including crashes. Read this link.
Generally I would advise you to replace your while loops with for loops, when the maximum number of iterations is already known. This makes the code easier to read and possibly faster as well.
Is there a reason you are using float for counter variables? That doesn't make sense.
'i = 30;' What is this supposed to mean? If your intention was to end the loop, use a break statement instead of some mysterious magic number. If your intention was something else, then your code isn't doing what you think it does.
You should include some error handling if the file was not found. fin = fopen(..) and then if(fin == NULL) handle errors. I would say this is the most likely cause of the crash.
Check the definition of found[] in the caller function. You're probably running out of bounds.
What I want to do is reverse a string of numbers that the user enters. what happens is it compiles and runs till i hit enter after the scanf. then I get some Microsoft runtime error... what's going wrong???
NOTE: this is homework, but i've got the logic figured out. what baffles me is this error.
#include <stdio.h>
int main()
{
unsigned int giveStr = 0;
char* charIt;
printf("Enter a number to be reversed.\t");
scanf("%d", &giveStr);
fflush(stdin);
sprintf(charIt, "%d", giveStr);
revStr(giveStr);
getchar();
return 0;
}
revStr(unsigned int n)
{
char buffer[100];
int uselessvar, counter = 0;
for (; n > 0;)
{
uselessvar = sprintf(&buffer[counter], "%d", n);
counter++;
}
for (counter = 0; counter > 0;)
{
printf("%c", buffer[counter]);
counter--;
}
return 0;
}
EDIT: flushing stdin for newlines :/ and also image here just not with that program. with mine.
You are trying to access memory which is not allocated in:
sprintf(charIt, "%d", giveStr);
Change char* charIt; to char charIt[50]; and all should be well (well, at least the segmentation fault part)
Also... pass charIt to revStr, as charIt contains the string with our number.
Then, a simple for loop in revStr will do the trick (what was the purpose of the second one, anyway?)
void revStr(char *giveStr)
{
int counter;
for (counter = strlen(giveStr)-1; counter >= 0; counter--)
{
printf("%c", giveStr[counter]);
}
printf("\n");
}
This will print each char our char representation has from the last one till the first one. You should read more on for loops.
For your home work problem, if you have the K&R book, turn to section 3.5 and read it thoroughly.
Note the functions reverse() and itoa(). They should give you a pretty good idea on how to solve your problem.
How does your program get out of the for (; n > 0;) loop? Won't counter simply increase until you get a bus error?
ED:
Respectfully, I think the claim that "i've got the logic figured out" is a little optimistic. :^) Doubtless someone will post the way it should have been done
by the time I'm done writing this, but it's probably worth drawing attention to what went wrong (aside from the memory allocation problems noted elsewhere):
Your first loop, "for (; n > 0;)", is strange because you're printing the entire number n into the buffer at counter. So why would you need to do this more than once? If you were selecting individual digits you might, but you're not, and obviously you know how to do this because you already used "sprintf(charIt, "%d", giveStr);". [Aside: giveStr isn't a great name for an unsigned integer variable!]
Your second loop also has strange conditions: you set counter to 0, set the condition that counter > 0, and then decrease counter inside. This obviously isn't going to loop over the characters in the way you want. Assuming you thought the first loop was character-by-character, then maybe you were thinking to loop down from counter-1 to 0?
for() or while() - which is BEST?
for (i=1; i<a; i++)
/* do something */
OR
i=1;
while (i<a) {
/* do something */
i++;
}
The first is the idiomatic way; it is what most C coders will expect to see. However, I should note that most people will also expect to see
for(i = 0; i < a; i++)
Note that the loop starts at zero. This will do something a times. If you're going to write a while loop that is equivalent to a for loop as above I strongly encourage you to write it as a for loop. Again, it is what C coders expect to see. Further, as a for loop it is easier to read as everything (initialization, loop condition, expression to be executed after each iteration) are all on one line. For the while loop they are spread out hindering readability.
Note, however, there are circumstances in which seemingly equivalent for and while loops are actually not. For example:
for(i = 0; i < 10; i++) {
if(i == 5) continue;
printf("%d\n", i);
}
and
i = 0;
while(i < 10) {
if(i == 5) continue;
printf("%d\n", i);
i++;
}
appear at first glance to be equivalent but they are not. The for loop will print 0--9 skipping 5 on the console whereas the while loop will print 0--4 on the console and then enter an infinite loop.
Now, that handles the simple case that you asked about. What about the more complex cases that you didn't ask about? Well, it really depends but a good rule of thumb is this: if you are going to repeat something a fixed pre-determined number of times, a for loop is generally best. Otherwise, use a while loop. This is not a hard-and-fast rule but it is a good rule-of-thumb. For example, you could write
unsigned int v;
unsigned int c;
for(c = 0; v; v >>= 1) c += v & 1;
but I think most C programmers would write this as
unsigned int v;
unsigned int c;
c = 0;
while(v) { c += v & 1; v >>= 1; }
Or, as another example, if you're going to read until the end of a file then you should use a while loop. Thus
FILE *fp;
fp = fopen(path, "r");
while(fgets(buf, max, fp) != NULL) { /* something */ }
instead of
FILE *fp;
for(fp = fopen(path, "r"); fgets(buf, max, fp) != NULL; ) { /* something */ }
Now, reaching into religious territory, this is why I prefer while(1) as the right way to do an infinite loop over for(;;).
Hope that helps.
It depends. What makes the reading most easy should be a guideline IMHO. If you know bounds beforehand you probably should use 'for'. Because it clearly says in one line where the looping starts, it ends and how to go from one element to the other.
Vote up for Dan McG - if the loop has a fixed count, etc., use for - it's more idiomatic. Classic cases of each:
for (i = 0; i < THRESHOLD; ++i) {
something;
}
Vs.
while (foo->next) {
foo = foo -> next;
}
Also: if you find yourself leaving out conditions in your for, consider what it would be like if you reworte it as a while.
At the end of the day: go back and read each version of the loop. Which one stands out more in your mind as "clear" in intent?
Which one makes most sense in the situation.
The for loop tells you it is most probably a fixed count loop. Starting at 1 ending before a.
The while loop doesn't imply any such thing, just that it ends once i >= a (at least from just reading the while (i<a){ at the top).
Of course, this isn't a rule and programmers generally do as they see fit, but it does make it easy to read through code without having to backtrack to comprehend some section.