Good morning.
I have received a task to build a C program, and I've encountered an annoying problem.
I'm trying to scan an unknown length string, which includes only numbers, '-' and spaces, and do something with that string.
The problem is, while scanning it, the program just stops doing anything after finding a minus. It doesn't want to scan any more characters afterwards.
The part where the loop doesn't being terminated:
while ((c = getchar()) != '\n' && c != EOF)
{
pStr[i++] = (char)c;
if (c == ' ')
numCounter++;
//if i reached maximize size then realloc size
if (i == current_size)
{
current_size = i + len_max;
pStr = realloc(pStr, current_size);
if (pStr == NULL)
{
printf("Memory allocation failure. \n");
exit(2);
}
}
}
pStr[i] = '\0';
.
.
.
When I was scanning a line that doesn't include minuses, the program did well. The only problem is while scanning a minus.
While debugging, this is the part where my program gets into infinite loop.
Can anyone please point me where's my mistake, so that the program could finally read a minus?
In general, the program gets a line of unknown length of numbers, minuses and spaces. The program would build a polynum. There is a Monom struct, and I want to build an array that would store, in each Monom value, the coefficient (index 0) and the power (index 1).
So my plan was to scan an unknown length string, check where I have numbers, and build a dynamic Monom array that will store the values. Ofcourse I have many more functions that are necessary, like converting a char value to int number, etc.
So far my only problem is the minus part. That could be very helpful if anyone can point me where's my mistake.
Thanks in advance!
Related
Something that I thought that would be pretty basic has me stumped.
If I have a char array char menuInput[3]; and do fgets(menuInput,3,stdin);, I can easily check if they entered nothing:
if(menuInput[0]=='\n')
{
printf("******You made no selection.******");
}
Or if they entered too many (in this case, more than one) characters:
else if(menuInput[1]!='\n')
{
printf("******Invalid Selection: Please enter a single digit option.******");
break;
}
In that case, the user is entering either no characters, exactly the right amount (one), or too many.
What is giving me trouble is checking when they could either enter no characters, up to n amount, or too many.
If I have char surname[SURNAME_MAX + 1];, and use fgets(surname,SURNAME_MAX + 1,stdin); where SURNAME_MAX is 12, I can't work out how to check whether the input falls within the 'acceptable' range.
I can easily see if the user has inputted anything at all (if surname[0]='\n') and if they have entered exactly 12 characters (with the 13th being the '\n').
I think the crux of things is here is just making sure that, somewhere, surname[SURNAME_MAX + 1] contains '\n', but I don't know how to do that in C.
Regards,
Doug
EDIT: Ok, I'm going with #R Sahu's answer, but am having trouble making it work properly.
I'm expecting, at most, the 12 characters defined by SURNAME_MAX.
This should mean that, by that answer, my array should be surname[SURNAME_MAX+3] ("need at least SURNAME_MAX+2 just to store the newline and the terminating null character")
Then I fgets(surname,SURNAME_MAX + 3,stdin); and then is it supposed to be:
while(strlen(surname)>SURNAME_MAX+2);
{
printf("Input is too long!\n");
printf("Surname (1-12 characters): ");
fgets(surname,SURNAME_MAX + 2,stdin);
}
?
Is that the correct way of implementing the answer?
It looks right to me, but, no matter what I enter, I'm getting the "Input is too long!" message.
EDIT 2: My bad, had some code in the wrong place, all good now.
You said:
What is giving me trouble is checking when they could either enter no characters, up to n amount, or too many.
My suggestion: If you are expecting to see at most N characters, create an array whose size is larger than N+2. You need at least N+2 just to store the newline and the terminating null character, and use fgets on that string. If the length of the string is greater than N+1, then you know they entered too many characters. Detecting whether they entered too few characters is simple. I think you will be able to figure it out.
For finding character in string, you can use strchr method:
char *pch;
pch=strchr(SURNAME,'\n');
if (pch != NULL)
{
// ok we've got \n in string
}
But I'm not sure it is the best way to solve this problem at all.
Suggest separating user input from variable checking/assignment.
First read in user input
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) {
// EOF or IO error occurred.
return;
}
Now qualify input; various methods exist.
int len = strlen(buf);
// lop off potential \n
if (buf > 0 && buf[len-1] == '\n') buf[--len] = 0;
if (len >= sizeof surname) {
// Input too long
return;
}
memcpy(surname, buf, len + 1);
I was trying an exercise from K&R (ex 1-17), and I came up with my own solution.
The problem is that my program appears to hang, perhaps in an infinite loop. I omitted the NUL ('\0') character insertion as I find C generally automatically attaches it to the end of a string (Doesn't it?).
Can somebody please help me find out what's wrong?
I'm using the GCC compiler with Cygwin on win8(x64), if that helps..
Question - Print all input lines that are longer than 80 characters
#include<stdio.h>
#define MINLEN 80
#define MAXLEN 1000
/* getlin : inputs the string and returns its length */
int getlin(char line[])
{
int c,index;
for(index = 0 ; (c != '\n') && ((c = getchar()) != EOF) && (index < MAXLEN) ; index++)
line[index] = c;
return (index); // Returns length of the input string
}
main()
{
int len;
char chArr[MAXLEN];
while((len = getlin(chArr))>0)
{
/* A printf here,(which I had originally inserted for debugging purposes) Miraculously solves the problem!!*/
if(len>=MINLEN)
printf("\n%s",chArr);
}
return 0;
}
And I omitted the null('\0') character insertion as I find C generally automatically attaches it to the end of a string (Doesn't it?).
No, it doesn't. You're using getchar() to read input characters one at a time. If you put the chars in an array yourself, you'll have to terminate it yourself.
The C functions that return a string will generally terminate it, but that's not what you're doing here.
Your input loop is a little weird. The logical AND operator only executes the right-hand-side if the left-hand-side evaluates to false (it's called "short-circuiting"). Rearranging the order of the tests in the loop should help.
for(index = 0 ; (index < MAXLEN) && ((c = getchar()) != EOF) && (c != '\n'); index++)
line[index] = c;
This way, c receives a value from getchar() before you perform tests on its contents.
I'm not positive about what's wrong, but you don't provide the input to the program so I'm guessing.
My guess is that in getlin your variable c gets set to '\n' and at that point it never gets another character. It just keeps returning and looping.
You never SET c to anything inside your getlin function before you test it, is the problem.
C does not insert a NUL terminator at the end of strings automatically. Some functions might do so (e.g. snprintf). Consult your documentation. Additionally, take care to initialize all your variables, like c in getlin().
1) C doesn't add a final \0 to your string. You are responsible for using an array of at least 81 chars and puting the final \0 after the last character you write in it.
2) You're testing the value of c before reading it
3) Your program doesn't print anything because printf uses a buffer for I/O which is flushed when you send \n. Modify this statement to print a final \n:
printf("\n%s",chArr);
to become:
printf("%s\n",chArr);
4) To send an EOF to your program you should do a Ctrl+D under unix and I don't know if it's possible for windows. This may be the reason why the program never ends.
I have the weirdest thing happening, and I'm not quite sure why it's happening. Basically what I need to do is use fgetc to get the contents of a simple ASCII file byte by byte. The weird part is it worked, but then I added a few more characters and all of a sudden it added a newline that wasn't there and read past the end of the file or something. Literally all I did was
do {
temp = (char*) checked_realloc (temp, n+1);
e = fgetc(get_next_byte_argument);
temp[n] = e;
if (e != EOF)
n++;
}
while (e != EOF);
And then to check I just printed each character out
temp_size = strlen(temp)-1;
for(debug_k = 0; debug_k < temp_size; debug_k++){
printf("%c", temp[debug_k]);
}
And it outputs everything correctly except it added an extra newline that wasn't in the file. Before that, I had
temp_size = strlen(temp);
But then it ended on some unknown byte (that printed gibberish). I tried strlen(temp)-2 just in case and it worked for that particular file, but then I added an extra "a" to the end and it broke again.
I'm honestly stumped. I have no idea why it's doing this.
EDIT: checked_realloc is just realloc but with a quick check to make sure I'm not out of memory. I realize this is not the most efficient way to do this, but I'm more worried about why I seem to be magically reading in extra bytes.
A safer way to write such operation is:
memset the memory bulk before use with zeros, if you are allocating memory prior to realloc.And every time you realloc, initialize it to zero.
If you are using a memory to access strings or use string functions on that memory always ensure you are terminating that memory with a NULL byte.
do{
temp = (char*) checked_realloc (temp, n+1);//I guess you are starting n with 0?
temp[n]=0;
e = fgetc(get_next_byte_argument);
temp[n] = e;
if (e != EOF)
n++;
} while (e != EOF);
temp[n]=0;
n=0;
I guess the above code change should fix your issue. You don't need strlen -1 anymore. :)
Cheers.
It sounds like you forgot to null terminate your string. Add temp[n] = 0; just after the while.
I'm trying to create a function to read Morse code from one file, convert it to English text, print the converted text to the terminal, and write it to an output file. Here's a rough start...
#define TOTAL_MORSE 91
#define MORSE_LEN 6
void
morse_to_english(FILE* inputFile, FILE* outputFile, char morseStrings[TOTAL_MORSE][MORSE_LEN])
{ int i = 0, compare = 0;
char convert[MORSE_LEN] = {'\0'}, *buffer = '\0';
//read in a line of morse string from file
// fgets(buffer, //then what?
while(((convert[i] = fgetc(inputFile)) != ' ') && (i < (MORSE_LEN - 1)))
{ i++;
}
if (convert[i + 1] == ' ')
convert[i + 1] = '\0';
//compare read-in string w/morseStrings
for (i = 48, compare = strcmp(convert, morseStrings[i]); //48 is '0'
i < (TOTAL_MORSE - 1) && compare != 0;
i++)
{ compare = strcmp(convert, morseStrings[i]);
}
printf("%c", (char)i);
}
I have initialized morseStrings to the morse code.
That's my function right now. It does not work, and I'm not really sure what approach to take.
My original algorithm plan was something like this:
1. Scan Morse code in from file, character by character, until a space is reached
1.1 save to a temporary buffer (convert)
2. loop while i < 91 && compare != 0
compare = strcmp(convert, morseString[i])
3. if (test ==0) print ("%c", i);
4. loop through this until eof
but.. I can't seem to think of a good way to test if the next char in the file is a space. So this has made it very difficult for me.
I got pretty frustrated and googled for ideas, and found a suggestion to use this algorithm
Read a line
Loop
-strchr() for a SPACE or EOL
-copy characters before the space to another string
-Use strcmp() and loop to find the letter
-Test the next character for SPACE.
-If so, output another space
-Skip to next morse character
List item
Endloop
But, this loops is kind of confusing. I would use fgets() (I think), but I don't know what to put in the length argument.
Anyways, I'm tired and frustrated. I would appreciate any help or insight for this problem. I can provide more code if necessary.
Your original plan looks fine. You're off by 1 when you check for the ' ' in the buffer, though. It's at convert[i], not convert[i + 1]. The i++ inside the loop doesn't happen when a space is detected.
I wouldn't use strchr(), to complicated.
Loop through the Inputfile reading a line
tokenize line with [strtok][1]
loop through tokens and save(best append) the single Letters to a Buffer
close looops and print
a bit of pseudocode for u
while(there is a next line){
tokens = strtok(line);
int i = 0;
while(tokens hasnext){
save to buffer}}
If you are concerned about the CPU time you can write a lookup table to find the values, something as a switch like this:
case '.-': code = "A"; break;
case '-...': code = "B"; break;
case '-.-.': code = "C"; break;
After you split the morse code by the spaces and send the diferent . and - combinations to the switch to get the original character.
I hope this help.
Best regards.
I'm learning C from the k&r as a first language, and I just wanted to ask, if you thought this exercise was being solved the right way, I'm aware that it's probably not as complete as you'd like, but I wanted views, so I'd know I'm learning C right.
Thanks
/* Exercise 1-22. Write a program to "fold" long input lines into two or
* more shorter lines, after the last non-blank character that occurs
* before then n-th column of input. Make sure your program does something
* intelligent with very long lines, and if there are no blanks or tabs
* before the specified column.
*
* ~svr
*
* [NOTE: Unfinished, but functional in a generic capacity]
* Todo:
* Handling of spaceless lines
* Handling of lines consisting entirely of whitespace
*/
#include <stdio.h>
#define FOLD 25
#define MAX 200
#define NEWLINE '\n'
#define BLANK ' '
#define DELIM 5
#define TAB '\t'
int
main(void)
{
int line = 0,
space = 0,
newls = 0,
i = 0,
c = 0,
j = 0;
char array[MAX] = {0};
while((c = getchar()) != EOF) {
++line;
if(c == NEWLINE)
++newls;
if((FOLD - line) < DELIM) {
if(c == BLANK) {
if(newls > 0) {
c = BLANK;
newls = 0;
}
else
c = NEWLINE;
line = 0;
}
}
array[i++] = c;
}
for(line = 0; line < i; line++) {
if(array[0] == NEWLINE)
;
else
printf("%c", array[line]);
}
return 0;
}
I'm sure you on the rigth track, but some pointers for readability:
comment your stuff
name the variables properly and at least give a description if you refuse
be consequent, some single-line if's you use and some you don't. (imho, always use {} so it's more readable)
the if statement in the last for-loop can be better, like
if(array[0] != NEWLINE)
{
printf("%c", array[line]);
}
That's no good IMHO.
First, it doesn't do what you were asked for. You were supposed to find the last blank after a nonblank before the output line boundary. Your program doesn't even remotely try to do it, it seems to strive for finding the first blank after (margin - 5) characters (where did the 5 came from? what if all the words had 9 letters?). However it doesn't do that either, because of your manipulation with the newls variable. Also, this:
for(line = 0; line < i; line++) {
if(array[0] == NEWLINE)
;
else
printf("%c", array[line]);
}
is probably wrong, because you check for a condition that never changes throughout the loop.
And, last but not least, storing the whole file in a fixed-size buffer is not good, because of two reasons:
the buffer is bound to overflow on large files
even if it would never overflow, people still wouldn't like you for storing eg. a gigabyte file in memory just to cut it into 25-character chunks
I think you should start again, rethink your algorithm (incl. corner cases), and only after that, start coding. I suggest you:
process the file line-by-line (meaning output lines)
store the line in a buffer big enough to hold the largest output line
search for the character you'll break at in the buffer
then print it (hint: you can terminate the string with '\0' and print with printf("%s", ...)), copy what you didn't print to the start of the buffer, proceed from that
An obvious problem is that you statically allocate 'array' and never check the index limits while accessing it. Buffer overflow waiting to happen. In fact, you never reset the i variable within the first loop, so I'm kinda confused about how the program is supposed to work. It seems that you're storing the complete input in memory before printing it word-wrapped?
So, suggestions: merge the two loops together and print the output for each line that you have completed. Then you can re-use the array for the next line.
Oh, and better variable names and some comments. I have no idea what 'DELIM' is supposed to do.
It looks (without testing) like it could work, but it seems kind of complicated.
Here's some pseudocode for my first thought
const int MAXLINE = ?? — maximum line length parameter
int chrIdx = 0 — index of the current character being considered
int cand = -1 — "candidate index", Set to a potential break character
char linebuf[bufsiz]
int lineIdx = 0 — index into the output line
char buffer[bufsiz] — a character buffer
read input into buffer
for ix = 0 to bufsiz -1
do
if buffer[ix] == ' ' then
cand = ix
fi
linebuf[lineIdx] = buffer[ix]
lineIdx += 1
if lineIdx >= MAXLINE then
linebuf[cand] = NULL — end the string
print linebuf
do something to move remnants to front of line (memmove?)
fi
od
It's late and I just had a belt, so there may be flaws, but it shows the general idea — load a buffer, and copy the contents of the buffer to a line buffer, keeping track of the possible break points. When you get close to the end, use the breakpoint.