Why is this loop (C) producing a segmentation error? - c

This is a C program that should accept the terminal's input and return the longest line of the input alongside the length of that line. I know it's not as efficient as it could be made, but I'm trying to write with the few functions I know right now. In running it, it returns a segmentation error. An online debugger points out line 30 (which is flagged in the code below) but doesn't specify the problem. I'm not sure of it either, and I've been looking. What is the source of this error?
By the way, I know that there might be other errors. I want to find those myself. I only need help with that segmentation error.
#include <stdio.h>
#define MAX 200
int start = 0;
int i, j, k, x, finish;
int longlength;
char text[MAX];
char longest[MAX];
int main()
{
fgets (text, MAX, stdin);
for (i = start; text[i] != EOF; i++)
{
if (text[i] == '\n')
{
finish = i - 1;
break;
}
}
for (j = start; j <= finish; j++)
{
longest[j - start] = text[j];
}
longlength = finish - start;
for (k = finish + 1; (text[k] = '\n') && (text[k] != EOF); k++)
{
start = k; //*****This is line 30*****
for (i = start; (text[(i + 1)] != '\n') && (text[(i + 1)] != EOF); i++)
{
}
finish = i;
if ((finish - start) > longlength)
{
longlength = (finish - start);
for (x = start; x <= finish; x++)
{
longest[(x - start)] = text[x];
}
}
}
printf ("This is the longest line : %s.\n Its length is %d.", longest, longlength);
return 0;
}

text[i] will never (or almost never) be EOF (which is usually defined to be -1), so your first loop won't terminate (unless the string contains a \n). Strings in C are null-terminated, and you should be checking for '\0', the null character.
You should try to run the code in a debugger, to see what's going on.

Strings in C are typically terminated by \0 that's why you have to set that as loop termination.
In your case:
for (i = start; text[i] != '\0'; i++)
{
//statements
}
Why do not use EOF:
You use it for Files, for instance .csv or normal .txt Files. Normal chararrays don't work with that.

Related

Trying to break out of fgets while loop

#include <stdio.h>
#include <string.h>
int main(){
char c[20], result[50];
int bool = 0, count = 0, i;
while(fgets(c,20,stdin) != NULL){
int stringSize = strlen(c);
if(stringSize == 11){
int ascii = (int)(c[i]);
for(i = 0; i < stringSize; i++){
if(ascii >= 'A' && ascii <= 'Z'){
bool = 1;
}
}
}
}
if(bool == 1){
count++;
strcat(result,c);
}
printf("%d", count);
printf("%s",result);
}
Good morning, I am fairly new to programming, and I've spent quite a while Googling and searching around for this issue already, but I can't seem to wrap my head about it.
Basically I'm trying to filter an fgets so that it reads each string, and if they're capital letters, they're "valid". However, I can't even get the fgets to stop accepting more input.
Edit: The idea is to store in result every String that has 10 capital letters, and for the fgets while loop to break once the user gives no input ('\0')
If you are entering strings from the standard input stream then it is better to rewrite the condition of the while loop the following way
while( fgets(c,20,stdin) != NULL && c[0] != '\n' ){
In this case if the user just pressed the Enter key without entering a string then the loop stops its iterations.
Pay attention to that fgets can append the new line character '\n' to the entered string. You should remove it like
c[ strcspn( c, "\n" ) ] = '\0';
Then you could write
size_t n = strlen( c );
if ( n == 10 )
{
size_t i = 0;
while ( i != n && 'A' <= c[i] && c[i] <= 'Z' ) ++i;
bool = i == 10;
}
Pay attention to that it is a bad idea to use the name bool because such a name is introduced as a macro in the header <stdbool.h>.
Also it seems this if statement
if(bool == 1){
count++;
strcat(result,c);
}
must be within the while loop. And the array result must be initially initialized
char c[20], result[50] = { '\0' };

C Program doesn't end after giving the correct output

So I'm trying to do a program that reads a sequence of numbers separated by spaces and new lines. The output should be the same sequence, but erasing unnecessary zeros(The sequence of charachters 'EOF' ends the program). Per example
01492 102934 should come out as 1492 102934
9312 0 01923 should come out as 9312 0 1923
0001249 0000 should come out as 1249 0
Well I've achieved that purpose but have come across a roadblock. The program doesn't exit unless I type the EOF sequence. Maybe it's because I have a while(1) running that gives an infinite loop. But when I try to delete it the program doesn't even print at all. I'm still learning this is for a school project.
Any help would be apreciated!
Here's the code:
#include <stdio.h>
int main(){
char c;
int i=0;
while(1){
c=getchar();
if (i==0){
if(c=='0'){
while (c=='0'){
c=getchar();
}
}
printf("%c",c);
i=i+1;
}
else if (c==' '){
printf("%c",c);
c=getchar();
if(c=='0'){
while (c=='0'){
c=getchar();
}
}
printf("%c",c);
}
else if (c=='E'){
c=getchar();
if (c=='O'){
c=getchar();
if(c=='F'){
printf("\n");
return 0;
}
}
}
else{
printf("%c",c);
}
}
}
The important stuff:
int c; // IMPORTANT, cannot be char
while (1) {
c = getchar();
if (c == EOF) break; // exit loop
// ...
}
There has to be some way to tell the program to exit.
With this, the program will exit on the letter x or two consecutive newlines or entering END.
getchar will return EOF when there is nothing left to read from a file. That can be simulated from stdin ( the keyboard) with ctrl + z on Windows or ctrl + d on Linux.
#include <stdio.h>
#include <string.h>
int main ( void) {
char done[4] = "";
int c = 0;
int prior = 0;
int reading = 0;
int zero = 1;
while ( EOF != ( c = getchar ( )) && 'x' != c) {
if ( '\n' == c && '\n' == prior) {
break;
}
if ( c >= '0' && c <= '9') {
reading = 1;
if ( '0' != c) {
zero = 0;
}
if ( ! zero) {
putchar ( c);
}
}
else {
if ( reading) {
if ( zero) {
putchar ( '0');
}
if ( ' ' == c || '\n' == c) {
putchar ( c);
}
else {
putchar ( ' ');
}
}
reading = 0;
zero = 1;
}
prior = c;
done[0] = done[1];
done[1] = done[2];
done[2] = c;
done[3] = 0;
if ( 0 == strcmp ( done, "END")) {
break;
}
}
putchar ( '\n');
return 0;
}
getchar() returns an int, not a char. If it only returned a char, there would be no way for it to return a value that indicates end of file, since all char values are valid and can’t be used for another purpose.
A motivating example in decimal system may be: A function checks the temperature returns a two-digit number. Any temperature between 0 and 99 is valid. How do you report errors when the thermometer is disconnected? You have to return a number with more digits, and use a special value like UNPLUGGED = 100.
But int is a wider type: it has many more values than char, and the “extra” values can be used to indicate some special condition that means “hey, this is not a valid character, but something else I had to tell you”.
getchar() returns the EOF constant upon failure (any failure), for example if no more input is available. There’s nothing sensible you can do even if the reason for the failure other than end of input. You should end processing at the first EOF.
Thus, change the type of c to int, and every time you call getchar(), you must check that its value is not EOF, and return when you encounter it.
The nested structure of your loops means that EOF checking has to be repeated all over the place. There are other ways to structure the code to keep this check in one place, but, admittedly, the nested loops have at least the potential to exploit the branch predictor, whereas a single getchar followed by a state-machine style switch statement will make it perform potentially worse. None of this matters in a simple homework problem, but it’s something to keep in mind. In any case, performance has to be benchmarked - no other way around it.
Try this code, I think it does what you requested:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int getLine(char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf("%s", prmpt);
fflush(stdout);
}
if (fgets(buff, sz, stdin) == NULL)
return -2;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff) - 1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? -1 : 0;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff) - 1] = '\0';
return 0;
}
int* convert2numbers(char* arr, int size) {
int i;
int j;
int k;
char token[100];
int* numbers;
int last_space = 0;
int index = 1;
int amount = 1;
// Count the amount of tokens.
for (i = 0; i < size; ++i) {
if (arr[i] == ' ') {
++amount;
}
}
numbers = (int *)malloc(amount * sizeof(int));
numbers[0] = amount;
for (j = 0; j <= size; ++j) {
if (arr[j] == ' ' || arr[j] == '\0') {
// Copy token from input string.
for (k = 0; k < j; ++k) {
token[k] = arr[k + last_space];
}
token[j] = '\0';
numbers[index] = atoi(token);
// Clear the token and continue.
memset(token, '\0', sizeof(token));
last_space = j;
++index;
}
}
return numbers;
}
int main(void) {
int i;
int size;
int* numbers;
int amount;
char input[100];
char help[] = "Numbers> ";
printf("Input numbers below or press enter to exit!\n");
while (1) {
getLine(help, input, sizeof(input));
// If input is empty exit.
if (input[0] == '\0') {
break;
}
size = strlen(input);
numbers = convert2numbers(input, size);
amount = numbers[0];
for (i = 1; i < amount + 1; ++i) {
printf("%d ", numbers[i]);
}
printf("\n");
}
return 0;
}
When run with these inputs this code outputs:
Input numbers below or press enter to exit!
Numbers> 01492 102934
1492 102934
Numbers> 9312 0 01923
9312 0 1923
Numbers> 0001249 0000
1249 0
Also if you press enter in console, it exits, as to escape the while(1) loop, easily.

C program stuck in infinite-loop-like nautre but without printing any variables

I'm trying K&R exercise 1-29 and honestly I'm stumped by what my program is doing. Upon inputting a small text file with gcc, the program just runs forever as if there's an infinite loop. Reading through my loops again I can't see any obvious mistakes, so I tried to print different variables to see what's happening, but nothing's printing to the command line - even the variable i from the very first for loop, not even once. Here's my code:
#include <stdio.h>
#define tabStop 10
#define maxInput 1000
int main(){
int i, c, b;
int m, t = 0;
int index, index2;
char input[maxInput];
int nonBlank;
for (i = 0; i<maxInput-1 && (c=getchar()) != EOF; ++i){
if (c != ' '){
input[i] = c;
}
else {
index = i; /*stores location in character array at start of blanks*/
for (b = 0; c == ' '; ++b, ++i); /*counts the number of blanks (b) until the next non-blank character*/
nonBlank = input[i]; /*saves the first seen non-blank character to be re-added later (as getchar() will have taken it in from input and will now stay at that point of the input)*/
index2 = i; /*stores location in character array at end of blanks*/
if (b >= tabStop){ /*if the tab space fits inside the number of blanks, otherwise there is nothing to be done*/
while (t < b){
t += tabStop;
++m;
}
for (int x = 0, i = index; i != index2 && x <= m; ++i, ++x){ /*loops over the number of tabs to be added starting from the first blank in the array found up until the first non-blank*/
input[i] = '\t';
}
while (i != index2){ /*if i did not reach index2 before x surpassed m, there exist remaining spaces to be filled with blanks*/
input[i] = ' ';
++i;
}
}
input[i] = nonBlank; /*puts the first seen non-blank character into place, as getchar() has already covered it and so it wouldn't otherwise be added like other non-blanks*/
}
}
input[i] = '\0';
printf("%s", input);
return 0;
}
Here's the inputted text file:
hello there world

C Program to Get Characters into Array and Reverse Order

I'm trying to create a C program that accepts a line of characters from the console, stores them in an array, reverses the order in the array, and displays the reversed string. I'm not allowed to use any library functions other than getchar() and printf(). My attempt is below. When I run the program and enter some text and press Enter, nothing happens. Can someone point out the fault?
#include <stdio.h>
#define MAX_SIZE 100
main()
{
char c; // the current character
char my_strg[MAX_SIZE]; // character array
int i; // the current index of the character array
// Initialize my_strg to null zeros
for (i = 0; i < MAX_SIZE; i++)
{
my_strg[i] = '\0';
}
/* Place the characters of the input line into the array */
i = 0;
printf("\nEnter some text followed by Enter: ");
while ( ((c = getchar()) != '\n') && (i < MAX_SIZE) )
{
my_strg[i] = c;
i++;
}
/* Detect the end of the string */
int end_of_string = 0;
i = 0;
while (my_strg[i] != '\0')
{
end_of_string++;
}
/* Reverse the string */
int temp;
int start = 0;
int end = (end_of_string - 1);
while (start < end)
{
temp = my_strg[start];
my_strg[start] = my_strg[end];
my_strg[end] = temp;
start++;
end--;
}
printf("%s\n", my_strg);
}
It seems like in this while loop:
while (my_strg[i] != '\0')
{
end_of_string++;
}
you should increment i, otherwise if my_strg[0] is not equal to '\0', that's an infinite loop.
I'd suggest putting a breakpoint and look what your code is doing.
I think you should look at your second while loop and ask yourself where my_string[i] is being incremented because to me it looks like it is always at zero...

Condition using EOF in C

The code below is my answer to exercise 1-13 in K&R The C Programming Language, which asks for a histogram for the length of words in its input. My question is regarding EOF. How exactly can I break out of the while loop without ending the program entirely? I have used Ctrl-Z which I have heard is EOF on Windows, but this ends the program, instead of just breaking the while loop. How can I get to the for loop after the while loop without ending the file? This is a general question, not just with my code below but for all the code in K&R that uses: while ((c = getchar()) != EOF). Thanks in advance!
`
#include <stdio.h>
#define MAXLENGTH 20 /* Max length of a word */
#define IN 1 /* In a word */
#define OUT 0 /* Out of a word */
int main() {
int c, i, j, len = 0;
int lenWords[MAXLENGTH];
bool state = OUT;
for (i = 0; i < MAXLENGTH; ++i) {
lenWords[i] = 0;
}
c = getchar();
while (c != EOF) {
if (c != ' ' && c != '\n' && c != '\t') {
if (state == IN) {
lenWords[len - 1] += 1; /* a length 5 word is in subscript 4 */
len = 0;
}
state = OUT;
}
else {
state = IN;
}
if (state == IN) {
len += 1;
}
c = getchar();
}
/* Generating a histogram using _ and | */
for (i = 0; i < MAXLENGTH; ++i) { /* Underscores write over one another; not so efficient */
for (j = 0; j < lenWords[i]; ++j) {
putchar('_');
}
putchar('\n');
for (j = 0; j < lenWords[i]; ++j) {
putchar('_');
}
putchar('|');
printf("Length: %d, Frequency: %d", i + 1, lenWords[i]);
}
return 0;
}
I think your question belongs on another network.
Answers here: Equivalent to ^D (in bash) for cmd.exe?
No. CtrlD on *nix generates a EOF, which various
shells interpret as running exit. The equivalent for EOF on Windows
is CtrlZ, but cmd.exe does not interpret this
specially when typed at the prompt.
Ctrl+D to sends EOF to standard input and stops the read on *nix.
Have a look here.
You have to check whether you use *nix or windows.
On Windows, EOF is represented by Ctrl+Z, whereas on *nix EOF is represented by Ctrl+D

Resources