简体   繁体   中英

Segmentation fault in C? Arrays, pointers, functions

Hi due to my lack of knowledge in C (second year in college). Compiler ate my code and built the app. But after accepting first value - numOfIntegers it stops working and debugging tells that the segmentation has been failed. SIGSEGV. How to fix that?

There is the code:

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

/* -----------------------------------------
    Program: Question 1
    Author: Maggot #9
    Email: maggot99999@gmail.com
    ID: B00076450
    Date: 16 September 2015
    Purpose: Who knows?
   ------------------------------------------ */

void wait(int);
void controlMenu(int, int[]);
int sumOfIntegers(int, int[]);
int avgOfIntegers(int, int[]);
int prodOfIntegers(int, int[]);
int minInteger(int, int[]);
int maxInteger(int, int[]);


const char * getName (int value)
{

  static char * arrayName[] = {"first","second","third", "fourth",
    "fifth","sixth", "seventh", "eighth", "ninth", "tenth"};

  static char badValue[] = "unknown";

  if (value<10 && value>=0)
    return arrayName[value];
  else
    return badValue;
}

int getValue(int numOfInteger)
{
  int value;
  wait(100);
  printf("Please enter %s the value:", getName(numOfInteger));
  scanf("%d",&value);

  return value;
}


void prepare(int * numOfIntegers)
{
  wait(300);
  printf("Hey again that C stupid lang\n\n");
  wait(200);
  printf("Please enter how many values you want to put: ");
  scanf("%d",numOfIntegers);
  return;
}


void initialize(int numOfIntegers,int* arrayNum[])
{
  int i;
  for(i=0; i<(numOfIntegers); i++)
    arrayNum[i] = getValue(i);

  wait(500);
  printf("\nPlease enter press any button to continue");
  wait(100);
  getch();
  wait(600);
  system("cls");
  wait(200);
  return;
}


int main()
{
  int numOfIntegers;
  prepare(&numOfIntegers);
  int arrayNum[numOfIntegers];
  initialize(numOfIntegers, &arrayNum[numOfIntegers]);
  controlMenu(numOfIntegers, &arrayNum[numOfIntegers]);
  return 0;
}


void controlMenu(int numOfIntegers, int arrayNum[])
{
  int i;
  char chooseNum;
  printf("Please choose any of the following:\n\n1. The integers accepted\n2. The sum of the integers\n3. The average of the integers\n4. The product of the integers\n5. The smallest integer\n6. The largest integer\n0. Exit menu\n");
  while(1)
  {
    chooseNum = getch();
    switch(chooseNum)
    {
      case '0':
        return;
      case '1':
        printf("\n>>> The integers are:");
        for(i=0; i<(numOfIntegers); i++)
          {
            printf("\n>>> The %s is %d", getName((i+1)), arrayNum[i]);
          }
        break;

      case '2':
        printf("\n>>> The sum of integers is: %d", sumOfIntegers(numOfIntegers, &arrayNum[numOfIntegers]));
        break;

      case '3':
        printf("\n>>> The average of integers is: %d", avgOfIntegers(numOfIntegers, &arrayNum[numOfIntegers]));
        break;

      case '4':
        printf("\n>>> The product of integers is: %d", prodOfIntegers(numOfIntegers, &arrayNum[numOfIntegers]));
        break;

      case '5':
        printf("\n>>> The smallest integer is: %d", minInteger(numOfIntegers, &arrayNum[numOfIntegers]));
        break;

      case '6':
        printf("\n>>> The largest integer is: %d", maxInteger(numOfIntegers, &arrayNum[numOfIntegers]));
        break;

      default:
        break;
    }
    printf("\n\n");
  }
}


int sumOfIntegers(int numOfIntegers,int arrayNum[])
{
  int sum=0;

  for(int i=0; i<(numOfIntegers); i++)
    sum += arrayNum[i];

  return sum;
}


int avgOfIntegers(int numOfIntegers, int arrayNum[])
{
  int average=0;

  average = sumOfIntegers(numOfIntegers, arrayNum[numOfIntegers])/numOfIntegers;

  return average;
}


int prodOfIntegers(int numOfIntegers, int arrayNum[])
{
  int i,product=0;

  for(i=0; i<(numOfIntegers); i++)
    product *= arrayNum[i];

  return product;
}


int minInteger(int numOfIntegers, int arrayNum[])
{
  int i,smallest=0;
  smallest = arrayNum[0];

  for(i=1; i<(numOfIntegers); i++)
    {
      if(smallest>arrayNum[i])
        smallest=arrayNum[i];
      else
        continue;
    }

  return smallest;
}


int maxInteger(int numOfIntegers, int arrayNum[])
{
  int i,largest=0;
  largest = arrayNum[0];

  for(i=1; i<(numOfIntegers); i++)
    {
      if(largest<arrayNum[i])
        largest=arrayNum[i];
      else
        continue;
    }

  return largest;
}


void wait(int ms)
{
  Sleep(ms);
  return;
}

I can see this fault in getName() which will access memory beyond the array bounds

if (value>10 || value<1)
    return arrayName[value];

I believe you are using the wrong test, try

if (value <= 10 && value > 0)
    return arrayName[value-1];

assuming value is in the range 1 .. 10 as the textual array implies.

2) a fault in GetValue where you input into numOfInteger but return value , which is uninitialised.

3) in prepare the statement

scanf("%d",&numOfIntegers);

will not pass the input value back to the caller. You should have either passed a pointer to the variable, or returned the value input.

But there might be a lot else wrong. Build your program step by step, checking and trying to break it as you go (with absurd input). Pay attention to compiler warnings - the second fault I listed will generate one.

EDIT okay... let's examine function prepare which after removing noise is

void prepare(int numOfIntegers)
{
    scanf("%d",&numOfIntegers);
    return;
}

This inputs a value to the function parameter that was passed. This is legal, since you can use a function argument in the same way you can a local variable (perhaps subject to const qualification).

Although it's not a coding error, it does not achieve anything. 1) you usually pass an argument like this to be used by the function in some way, perhaps in its limits and/or in its prompt. 2) Altering the argument like this will not find its way back to the caller.

Here are two ways to deal with this.

A) the function returns the input value

int prepare(void)
{
    int value;
    scanf("%d", &value);    // the address of value
    return value;
}

...

int input = prepare();
printf("%d\n", input);

B) the function takes a pointer argument

void prepare(int *value)
{
    scanf("%d", value);     // value is already a pointer
}

...

int input;
prepare(&input);
printf("%d\n", input);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM