-1

In a nutshell, I have to be able to return the character in the middle of an input (char array) for part of our first C assignment. What I have so far, however, is code that returns "Segmentation fault (core dumped)". I read into this a little bit, and learned that essentially I may be trying to access/modify data that is "not available to me", so-to-speak. Here is my code:

#include <stdio.h>
#include <string.h>

char input[30];
int inputLen;
char midChar;

int main()
{
    printf("Type in some text, and the press the Return/Enter key: ");
    fgets(input,sizeof(input),stdin);
    printf("\nYour input: %s",input);
    inputLen = strlen(input)-1;
    printf("Length of your input is %d characters.",inputLen);

    if((inputLen % 2) == 0) {
        midChar = input[(inputLen/2)+1];    // >>> PROBLEM HERE <<<
    }
    else {
        midChar = input[((inputLen+1)/2)+1];    // >>> PROBLEM HERE <<<
    }
    printf("%s",midChar);
    return 0;
}

The two lines with >>> PROBLEM HERE <<< are the lines which I believe I've narrowed down to be the source of the problem.

Please Note: I have taken an introductory class in Java, and last semester took a class half-devoted to MATLAB, so I do have a little bit of programming intuition -- However, I am a 100% beginner in C, so I would appreciate some clear elaboration behind any help you guys may offer. I am not familiar with most functions/syntax unique to C, so I'm sure there will be cringe-worthy lines of code above for those well-versed in this language. If this is the case, feel free to include any other tips in your answers. Thanks!

Jacob M
  • 147
  • 3
  • 10

4 Answers4

4

You're printing a char with %s, so the program is treating your input as a pointer (to a char array). It's not a valid such thing.

You meant %c for a single character.

Your compiler should tell you about this. Turn warnings on!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

A late addition:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  // This will be the default value if a string of length 0 is entered
  char midChar = 0;
  int inputLen;
  int bufferLen = 31;
  char* input = (char*)malloc(sizeof(char) * bufferLen);

  printf("Type in some text, and the press the Return/Enter key: ");
  fgets(input, bufferLen, stdin);

  printf("\nYour input: %s", input);
  inputLen = strlen(input);

  if (input[inputLen - 1] == '\n') {
    inputLen--;  // ignore new line character
  }
  printf("Length of your input is %d characters.\n", inputLen);

  if (inputLen > 0) {
    midChar = input[inputLen / 2];  // take right of middle for even number
  }

  printf("%c\n", midChar);
  return 0;
}

In your previous post you used sizeof(input) which is not recommended for reasons described in this post. It is better practice to hold the length of the array in a separate variable, here bufferLen.

Also the use of global variables here input inputLen midChar is generally discouraged as they lead to unexpected behaviour during linking and make program flow harder to understand.

I initialised the memory for the buffer dynamically so the bufferLen could be changed in the program.

When computing the length of the input one must consider the newline character \n which is retained if a small enough string is entered but not if the entered string exceeds the bufferLen.

For strings with even lengths I arbitrarily took the character to the right. The inputLen zero case is also handled.

This whole answer is only an addition to the first one which already found the bug correctly, because I was late to the party.

Lukas Koestler
  • 328
  • 3
  • 10
1

Other than print char problem, I think there is also a problem at where you indicated.

ex. if input string is abc, inputLen will be 3, midchar index should be at 1 since array index in C start from 0. However ((inputLen+1)/2)+1 gives 3. This probably won't directly cause the segfault but will give wrong answer.

You can replace

    if((inputLen % 2) == 0) {
        midChar = input[(inputLen/2)+1];    // >>> PROBLEM HERE <<<
    }
    else {
        midChar = input[((inputLen+1)/2)+1];    // >>> PROBLEM HERE <<<
    }

with

midChar = input[inputLen/2];

since C will truncate when doing integer division.

 a    b    c -> 3/2 = 1
[0]  [1]  [2]
 a    b    c    d  -> 4/2 = 2
[0]  [1]  [2]  [3]

Other than that, you also need to make sure the inputLen is not 0

J.Z
  • 411
  • 3
  • 14
1

Although "pretty lady" (@LightnessRasesInOrbit) up here is correct, let me explain what is happening when you do this:

printf("%s\n", charVar);

or this:

printf("%s\n", intVar);

or this:

printf("%s\n", floatVar);

Or when you print things using pritnf() with %s. You have to understand how does printf ("%s", string) work!! So when printf gets %s it looks for C string or in other words, character array terminated with '\0'. If it does not '\0' it will segfault. In depth, printf() works like this:

char name[4];
printf("Hello ", name);

now printf does following:

  1. gets the size of 1st variable ("Hello")
  2. gets the size of 2nd variable (name) How? Simple by this loop:

    int varSize;
    for (varSize = 0; varSize != '\0'; ++varSize);
    
  3. moves "Hello" into buffer

  4. Determine the size of second parameter. How, by doing this:
  5. does following

    if ("%d")
         // read intVar and attach it to the buffer
    if ("%f")
         // read floatVar and attach it to the buffer
    if ("%s")
        for (int i = 0; stringVar[i] != '\0'; ++i)
            // push each char into the buffer
    

So I hope you see what is happening if one of for() loops does not find '\0' character. If you do good if you don't well it continues reading through until it segfaults.

NOTE: This is oversimplified pseudo code on how printf() works and is not actual implementation, this is only for OP to understand what is going on.