fgetc() doesn't work properly - c

I have file that goes like 7 4 5 1 etc. I want to put these number in a multi-dimensional array.
for(x=0;x<9;x++)
for(y=0;y<9;y++)
{
current=fgetc(fp);
if(current!=EOF&current!=' '&current!='\n')
sudokuArray[x][y] = current-'0';
}
This code doesn't work properly. sudokuArray[0][0] gives the result true(first number in the file) but [0][1] gives some random number like 131231304. [0][2] gives what [0][1] supposed to be. Why is that?

It's because if your inner loop:
for(y=0;y<9;y++)
{
current=fgetc(fp);
if((current!=EOF) && (current!=' ') && (current!='\n'))
sudokuArray[x][y] = current-'0';
}
If your input is 7 4 5 1, then when y == 0, you read '7', which gets put in sudokuArray[0][0].
Now on your next loop, y == 1, and you read ' '. Because of your if statement, you don't put that in sudokuArray but y still gets incremented.
Next time you do the loop, y == 2, you read '4' and it gets put in sudokuArray[0][2].
So fgetc() does work properly and your code is doing exactly what you told it to do. Code is very obedient that way.
Edit: Also note your if statement should contain && instead of &. They are different operators. A little whitespace and some parenthesis make the code easier to read and maintain as well.

I am not sure why you use nested loops to read from file. I see one problem in your code:
Change & to &&:
if(current!=EOF&current!=' '&current!='\n')
to:
if(current!=EOF && current!=' ' && current!='\n')
&& is the logical AND and & is bitwise AND.
Since, you have only integers and you seem to know the exact no. of integers. You can simply use fscanf:
fscanf(fp, "%d", &arr[x][y]);

Inside your loop you're ignoring characters - but then you're incrementing the indexes even though you haven't filled the related array element. Try re-implementing as:
#include <stdlib.h>
for(x=0;x<9;x++)
for(y=0;y<9;y++)
{
/* Get next character */
current=fgetc(fp);
/* Loop, retrieving additional chars, until either EOF is hit or
you find a non-whitespace character */
while(current != EOF && iswhite(current))
current = fgetc(fp);
if(current != EOF)
sudokuArray[x][y] = current - '0';
}
Also - do you want to check current != EOF, or should this be !feof(fp)?
Share and enjoy.

Related

C Integer range must meet 3 different conditions

If I wanted to limit the range of values to be assigned to an integer to three different conditions. eg; Must be between 9 and 95 and also be divisible by 5 would this be the correct way to accomplish this?
I've been told that i can have multiple conditions as long as they are separated by && but I am having little success with my code.
if (input >= 5 && input <= 95 && input %5)
Your code seems fine to me, except for this line.
if (input >= 5 && input <= 95 && input %5)
The expression input % 5 returns the remainder of input/5. You want input to be divisible by 5, which happens when input % 5 returns a remainder of 0. Since C interprets 0 as false, and pretty much all other integers as true, this expression will do exactly the opposite of what you want it to do. Try using
if (input >= 5 && input <= 95 && (input % 5 == 0))
That should do what you want it to do.
There are a number of issues with your code as it stands. First, the outright bugs:
The expression input % 5 will give you the remainder when divided by five. This means you will get zero if it is a multiple, non-zero otherwise. Unfortunately, zero is treated as false so this will only be true if input is not a multiple. The correct expression is (input % 5) == 0.
If you enter something that cannot be interpreted as an integer, the scanf will fail and input will be left at whatever value it was beforehand. This should be caught and acted upon, by checking the return value - this gives you the number of items successfully scanned so should be one.
Your code seems to return the value if okay but return nothing if it's invalid.
Next, while not bugs, these things are my personal preferences which can make code easier to read and maintain:
I prefer to explicitly separate sub-expressions so I never have to worry about precedence rules (provided it doesn't make the expression unreadable in the process). To that end, I would make the full if statement if ((input >= 5) && (input <= 95) && ((input % 5 == 0)).
I'm not a big fan of the if (condition) transferControl else ... construct since the else is totally superfluous.
I also prefer error catching to be done in a localised fashion at the start, catching problems early. Only after all checks are passed do you do the success portion.
A function (assuming it is a function, which seems likely) should generally do one thing, such as check if the value is valid. Writing issues to standard output is probably best left to the caller so that the function is truly re-usable. It would be better to have a function do the check and return some value to indicate whether or not there was a failure, along with the value if valid.
It's usually better to use puts("something") rather than printf("something\n"). The printf call is best left to where you actually need to do argument formatting.
Taking that all into account, the code that I would posit would be along the lines of:
#include <stdbool.h>
bool InputValidRangeAndMultiple(
unsigned *pValue,
unsigned minVal,
unsigned maxVal,
unsigned multVal
) {
unsigned input;
// If no unsigned int available, error.
if (scanf("%u", pValue) != 1) return false;
// If value invalid in any way (range or multiple), error.
if ((*pValue < minVal) || (*pValue > maxVal)) return false;
if ((*pValue % multVal) != 0) return false;
// Value is now deemed okay.
return true;
}
Calling that function can be done thus, with the prompts and errors handled outside the "input and check" function:
#include <stdio.h>
unsigned value;
puts("Enter Value.\nValue must be divisible by 5 and within 5 and 95...");
if (! InputValidRangeAndMultiple(&value, 5u, 95u, 5u)) {
puts("Invalid input...");
returnOrDoSomethingIntelligent();
}
// The 'value' variable is now valid.

Array-member comparison in a function not working

First of all I'm not even sure whether you call it a member, couldn't think of a better term.
I'm trying to learn basics of debugging and arrays - so I wanted to create something resembling insert-sort from memory (so mistakes would be made) and then debug the program.
void findingsmaller (int *array, int num_inputs){
int a = 0;
int b = 1;
for ( b=1; b == num_inputs-1; b++ ) {
if ( array[a] > array[b] ) {
goleft(array, a, b);
a++;
}
}
}
Let's say we have this in array: 6 5 3 1 8 7 2 4. array[a] should be 6 and array[b] should be 5. 6 > 5 so we should enter the function that would find the first smaller number on the left of the array.
From my debugging session it seems like the condition is FALSE so I don't enter goleft at all. More specifically, Step into ignores it, the testing printf wasn't executed either. I'm assuming the array comparison is not written properly, what's the correction?
WHOLE CODE if somebody wants to see other possible mistakes.
Thank you in advance!
EDIT: <= num_inputs is correct, somehow I thought for has (range1, range2, change) instead of (start, condition, change). Anyway, now the problem seems that my goleft function does its do-while cycle one time too many although it shouldn't get past that condition.
EDIT2: A couple of other mistakes were fixed.
My printing in main is now for( ; i <= num_inputs-1; )
My goleft would do too many iterations due to the condition, fixed into ... while ( a >= 0 && array[a] > array[b] )
My findingsmaller would only operate if the number next is smaller but does nothing when the number is greater. For example for 6 8 the program wouldn't function properly. Added else {a++}
My fixed code for anyone interested in the comparison of the changes.
The for loop is executed as long as the condition is True.
for ( ;Condition; )
{
// body
}
In your for loop, the condition is always False if the input is greater than 1.
Instead of b == num_inputs - 1, you should put b < num_inputs in your for loop condition. Since the equality isn't true on the first iteration of the loop, it is immediately breaking.
I was looking a little bit at your code and i notice something that doesnt work.
while (scanf("%d", &array[i]) != EOF)
As the documentation of the function scanf say :
The return value is EOF for an error
your while condition was making you num_imputs reaching 200 even if there was only 3 inputs. I would replace EOF by '\n'.
while (scanf("%d", &array[i]) != '\n') /* stop when the user input '\n' you
can replace with any character you want to make it stop. */
I did not make a lot of test but this should make your program work fine.

difference for and while loops file i/o

i write a code which takes values from text file and write in a text file, so I'm stuck on for and while reading end of file i think both of codes are right there is no any difference btw them,however I get difference. I'm unable to understand. Besides is there other way to read eof ? Thank you all appreciated answers.
for(st=(fscanf(fptr_in,"%c",&ch));
st==1;
st=(fscanf(fptr_in,"%c",&ch))){
the other
st=(fscanf(fptr_in,"%c",&ch));
while(st==1)
st=(fscanf(fptr_in,"%c",&ch));
The conditionals are different. In the for you are using the return value of fscanf which is an int. When an int is used as a conditional, it is the same thing as != 0:
int x;
if( x ) {}
//equiv to:
if( x != 0 ){}
In the while loop, you explicitly check if the return value is a 1. So, if you change your for loop to
for( (st=(fscanf(...)) == 1 )
(or conversely remove the ==1 from the while loop) they should produce the same behavior.

K&R Exercise 1-21 - Mental incomprehension

The "impossible" K&R exercise.
"Write a program entab that replaces
strings of blanks by the minimum
number of tabs and blanks to achieve
the same spacing. Use the same tab
stops, say every n columns. Should n
be a variable or a symbolic
parameter?"
The problem I'm having is, I'm unsure about how to even do this correctly. I know it's not very explanatory, but that's pretty much the problem here. Most of the examples I've seen have counted a number of blanks, and replaced those series with a tab, but this isn't what its asking, I reckon I understand what its asking, but currently feel unable to do this.
Could anyone help :)
Edit: The code I've written so far can be found here.
If your question is "What is this asking me to do?" I think I can help by paraphrasing the original question (posing the same question in a different way).
Write a program that takes as input text with spaces and produces as output visually equivalent text using tabs to the maximum extent possible.
For example, with tabstops every 8 characters, and showing spaces as '.' and tabs as '-';
input;
".foo:...bar;......#comment"
output;
".foo:-bar;-..#comment"
input;
".......-foo:.....bar;......#comment"
output;
"-foo:-.bar;-...#comment"
Write the program so that tabstop parameter n can be varied, i.e. allow values of n other than 8. Be prepared to justify your decision to make n a constant, or alternatively a variable.
Edit I had a look at your code and I think it is more complex than it needs to be. My advice is to do it a character at a time. There's no need to buffer a whole line. Maintain a column count as you read each character ('\n' resets it to zero, '\t' bumps it by 1 or more, other characters increment it). When you see a space (or tab), don't emit anything right away, start your entabbing process, emit zero or more tabs and then spaces later (at '\n' or a non whitespace character, whichever comes first).
A final hint is that a state machine can make this kind of algorithm a lot easier to write, validate, test and read.
Edit 2 In a shameless attempt to get the OP to accept my answer, I have now gone ahead and actually coded a solution myself, based on the hints I offered above and my comment in the discussion.
// K&R Exercise 1-21, entab program, for Stackoverflow.com
#include <stdio.h>
#define N 4 // Tabstop value. Todo, make this a variable, allow
// user to modify it using command line
int main()
{
int col=0, base_col=0, entab=0;
// Loop replacing spaces with tabs to the maximum extent
int c=getchar();
while( c != EOF )
{
// Normal state
if( !entab )
{
// If whitespace goto entab state
if( c==' ' || c=='\t' )
{
entab = 1;
base_col = col;
}
// Else emit character
else
putchar(c);
}
// Entab state
else
{
// Trim trailing whitespace
if( c == '\n' )
{
entab = 0;
putchar( '\n' );
}
// If not whitespace, exit entab state
else if( c!=' ' && c!='\t' )
{
entab = 0;
// Emit tabs to get close to current column position
// eg base_col=1, N=4, col=10
// base_col + 3 = 4 (1st time thru loop)
// base_col + 4 = 8 (2nd time thru loop)
while( (base_col + (N-base_col%N)) <= col )
{
base_col += (N-base_col%N);
putchar( '\t' );
}
// Emit spaces to close onto current column position
// eg base_col=1, N=4, col=10
// base_col -> 8, and two tabs emitted above
// base_col + 1 = 9 (1st time thru this loop)
// base_col + 1 = 10 (2nd time thru this loop)
while( (base_col + 1) <= col )
{
base_col++;
putchar( ' ' );
}
// Emit buffered character after tabs and spaces
putchar( c );
}
}
// Update current column position for either state
if( c == '\t' )
col += (N - col%N); // eg col=1, N=4, col+=3
else if( c == '\n' )
col=0;
else
col++;
// End loop
c = getchar();
}
return 0;
}
I'm a bit late, but here's how I solved it myself. It's a different approach than what has been shared above, so please share any comments/feedback if you have any.
Check out my public gist on Github for the source code. There's comments on the code, and the approach is explained on the top of the file, but I'll copy and paste it here just so that the logic is clear from the get-go.
Approach:
We'll keep track of number of spaces encountered (between nontab/nonspace characters)
We'll keep track of characters (that aren't tabs/blanks/newlines) per input line
We'll evaluate the "gaps" generated by spaces by:
Evaluating whether the number of spaces in between those characters.
A gap will be "big enough" when the number of spaces is >= TABSIZE
Then, for all the left over spaces in our "buffer", we'll print them out individually
Finally, we print out the character that was read in (which was not a tab/blank)
As well as updating space count and character count if necessary.
I'm still a novice programmer in all senses, so I am not sure of how it would compare vs the other solutions posted in here, but the logic seems easier to follow (at least for me).
Hope this helps someone later on!
I agree with your assessment. It won't be enough to replace every n blanks with a tab; for example, if n == 4, "hi blank blank blank blank" should not be replaced by "hi tab", but rather by "hi tab blank blank".
It sounds like what you need to do is keep track of the current position as you're reading in each line, and use this information to determine how many tabs you need. Does this help? Please let me know if you need more details!
As for the "variable vs. symbolic parameter" part, either would definitely be viable, but I can think of one significant advantage to using a variable: you can run the program for different values of n without recompiling.
My understanding is that you don't really have to know what the problem is or how to solve it in order to answer this question. The question seems to asking whether you understand when to use variables instead of "symbolic parameters". I'm not actually sure what is meant by "symbolic parameter"; it seems to be outdated nomenclature.
Having said that, solving the first part of the question (replacing spaces with tabs) is rather straight forward. Think division and remainders.
I took a very cursory look at your code, and nothing is jumping out at me as blatantly wrong.
So my advice would be to either single-step through a few input examples in a debugger, examining variable values as you go, or add a whole bunch of debugging print statements. In either case, your goal is to find the point where the state of the program starts to deviate from what you expected or intended.
I am currently plowing KnR and came across this page:
Answers to Exercises
Your exercise are located under:
Solutions
Chapter 1 - A Tutorial Introduction
Ex No 21 Pg No 34
users.powernet.co.uk/eton/kandr2/krx121.html
Hopefully you find this useful.
Sincerely,
Morpfh
1: http://users.powernet.co.uk/eton/kandr2/index.html "The C Programming Language", 2nd edition, Kernighan and Ritchie - Answers to Exercises
In the top rated answer above, the program is overly complex.
In an attempt to simplify that part of the answer, I've attached a much simpler code hopefully written in the style of K&R (mostly by incrementing inline with ++).
include
define TAB 4
int main(){
char newsentence[255],c;
int spacecount = 0, oldsentencepointer = 0, newsentencepointer = 0;
printf("Give me a sentence please:\n");
while ((c = getchar()) != '\n') {
if ((oldsentencepointer != 0) && (oldsentencepointer % TAB == 0) && (spacecount > 0))
{
newsentencepointer -= spacecount; //if at tabstop, and spaces and not
first, go back to 1st space, set tab.
newsentence[newsentencepointer++] = '\t';
spacecount = 0;
}
if (c == ' ') {
newsentence[newsentencepointer++] = ' ';
spacecount++; //keep track of spaces before tab stop
}
else if (c == '\t') {
newsentence[newsentencepointer++] = '\t' ;
oldsentencepointer = TAB; //set old pointer to TAB (does not matter if actual,
only cadence important)
continue; //continue from here so as not to increment
old sentence counter.
}
else {
newsentence[newsentencepointer++] = c ; //write whatever was old into new.
spacecount = 0; //reset space counter.
}
oldsentencepointer++;
}
newsentence[newsentencepointer] = '\0'; //cap it off.
puts(newsentence);
return 0;
}
There is an even more concise solution, although it does not employ the best code practices available (abusing short circuit evaluation, awkward control flow via continue, somewhat weird "space" loop).
#include <stdio.h>
#define TS 8
int main(int arg, char *argv[]) {
int counter = 0, space_counter = 0, c;
while ((c = getchar()) != EOF) {
++counter;
if (c == ' ' && ++space_counter && (counter % TS) == 0) {
space_counter = 0;
c = '\t';
} else if (c == '\t') {
counter = space_counter = 0;
} else if (c != ' ') {
while (space_counter--)
putchar(' ');
space_counter = 0;
if (c == '\n')
counter = 0;
} else {
continue; /* don't call putchar(c) */
}
putchar(c);
}
return 0;
}
Except for blanks, every character that is read is printed verbatim. Blanks are counted instead. If the program encounters a non-blank character, it prints as many blanks as it has counted before, resetting that counter afterwards. If it encounters a blank, it checks via a second counter (printed characters since the beginning of the line/last tabstop) if the cursor is on a tabstop. If it is, a tab is printed, otherwise the blank is just counted.
A tab in the input is dealt with resetting the space counter and outputting the tab, eliminating any superfluous blanks in the process.

Counting Syllables one char at a time [C]

I'm writing a program which reads text from a file, and determines the number of sentences, words, and syllables of that file. The trick is, it must only read one character a time, and work with that. Which means it can't just store the whole file in an array.
So, with that in mind, heres how my program works:
while(character != EOF)
{
check if the character is a end-of-sentence marker (?:;.!)
check if the character is whitespace (' ' \t \n)
(must be a letter now)
check if the letter is a vowel
}
Using a state-machine approach, each time the loop goes through, certain triggers are either 1 or 0, and this effects the count. I have had no trouble counting the sentences or the words, but the syllables are giving my trouble. The definition for syllable that I am using is any vowel or group of vowels counts as 1 syllable, however a single e at the end of a word does not count as a syllable.
With that in mind, I've created code such that
if character = 'A' || 'E' ... || 'o' || 'u'
if the last character wasnt a vowel then
set the flag for the letter being a vowel.
(so that next time through, it doesnt get counted)
and add one to the syllable count.
if the last character was a vowel, then dont change the flag and don't
add to the count.
Now the problem i have, is my count for a given text file, is very low.
The given count is 57 syllables, 36 words, and 3 sentences. I get the sentences correct, same with the words, but my syllable count is only 35.
I also have it setup so that when the program reads a !:;.? or whitespace it will look at the last character read, and if that is an e, it will take one off the syllable count.
This takes care of the e being at the end of a word not counting as a vowel.
So with this in mind, I know there must be something wrong with my methodology to get such a vast difference. I must be forgetting something.
Does anyone have some suggestions? I didn't want to include my entire program, but I can include certain blocks if necessary.
EDIT: Some code...
I have if ( end-of-sentence marker), then else if (whitespace), then the final else which entails that only letters which can form words will be in this block. This is the only block of code which should have any effect on the counting of syllables...
if(chrctr == 'A' || chrctr == 'E' || chrctr == 'I' || chrctr == 'O' || chrctr == 'U' || chrctr == 'a' || chrctr == 'e' || chrctr == 'i' || chrctr == 'o' || chrctr == 'u')
{
if(chrctr == 'E' || chrctr == 'e')
{
isE = 1;
}
else
{
isE = 0;
}
if(skipSylb != 1)
{
endSylb = 1;
skipSylb = 1;
}
else
{
endSylb = 0;
skipSylb = 1;
}
}
else
{
endSylb = 0;
skipSylb = 0;
}
So to explain... endSylb if 1, later in the program will add one to the count of syllables. skipSylb is used to flag if the last character was also a syllable. If skipSylb = 1, then this is a block of vowels and we only want to add one to the counter. Now I have an isE variable, which just tells the program next time around that the last letter was an E. This means, next time through the while loop, if it is an end of sentence, or whitespace, and the last letter was E (so isE = 1), then we have added one too many syllables.
Hopefully that helps.
Since the value is actually lower then what it should be, i thought perhaps the statements where i minus from the count are important too.
I use this if statement to decide when to minus from the count:
if(isE == 1)
{
countSylb --;
}
This statement happens when the character is whitespace, or an end of sentence character.
I can't think of anything else relevant, but i still feel like im not including enough.
Oh well, let me know if something is unclear.
I also have it setup so that when the program reads a !:;.? or whitespace it will look at the last character read, and if that is an e, it will take one off the syllable count.
This sounds wrong. What about words like "die" and "see"?
Obviously you can only decrement the count if the word counted for more than one syllable.
In your case decrementing if the 'e' at the end was not part of a vowel group might suffice.
If that doesn't help: Maybe you don't clear the vowel flag after reading a consonant? I can't tell from your code.
What could really help you is debugging outputs. Let the program tell you what it is doing like:
"Read a vowel: e"
"Not counting the vowel e because [...]"
You need a Finite State Machine
In a sense, every program is a state machine, but typically in the programming racket by "state machine" we mean a strictly organized loop that does something like:
while (1) {
switch(current_state) {
case STATE_IDLE:
if (evaluate some condition)
next_state = STATE_THIS;
else
next_state = STATE_THAT;
break
case STATE_THIS:
// some other logic here
break;
case STATE_THAT:
// yet more
break;
}
state = next_state;
}
Yes, you can solve this kind of program with general spaghetti code. Although legacy spaghetti code with literal jumps isn't seen any more, there is a school of thought which resists grouping lots and lots of conditionals and nested conditionals in a single function, in order to minimize cyclomatic complexity. To mix metaphors, a big rat's-nest of conditionals is kind of the modern version of spaghetti code.
By at least organizing the control flow into a state machine you compress some of the logic into a single plane and it becomes much easier to visualize the operations and make individual changes. A structure is created that, while rarely the shortest possible expression, is at least easy to modify and incrementally alter.
Looking at your code, I suspect some of the logic has gotten lost in the excessive size. Your main snippet appears equivalent to something like this:
chrctr = tolower(chrctr);
if (strchr(chrctr, "aeiou")) {
isE = (chrctr == 'e');
endSylb = !skipSylb;
skipSylb = 1; // May not be you want, but it's what you have.
}
else {
skipSylb = endSylb = 0;
}
Personally, I think trying to count syllables algorithmically is nearly hopeless, but if you really want to, I'd take a look at the steps in the Porter stemmer for some guidance about how to break up English words in a semi-meaningful way. It's intended to strip off suffixes, but I suspect the problems being solved are similar enough that it might provide at least a little inspiration.

Resources