I keep getting a segmentation fault in the line array[j]=array[j]+1.
I've included the portion of the main function used to call "mode", function which is the one I'm having trouble with. The program is supposed to take user input in the form of a string. Depending on what the string says the function does different things. For input "mode" it takes an array from the user and then finds the mode, or number that appears most often. The program may not be the cleanest or most efficient, but I just need it to work. Thank you for any help.
int mode(int input[]){
int array[30]={0},i=0,j=0,i2=0,j2=0;
while (input[i]!='\0'){
j=input[i];
array[j]=array[j]+1;
i++;
}
while (array[i2]!='\0'){
if (array[i2]>j2){
j2=array[i2];
i2++;
}
else{
i2++;
}
}
return j2;
}
int main(){
char function_called[7];
int nums_for_mode[50],num_for_primes;
int num1,den1,num2,den2;
printf("Please choose a function (mode, primes, or fradd): ");
scanf("%s",&function_called);
if(strcmp(function_called, "mode")==0){
printf("\nPlease provide numbers between 1 and 30: ");
scanf("%i",&nums_for_mode);
printf("\nThe mode is %i\n",mode(nums_for_mode));
}
nums_for_mode is uninitialized, and you don't terminate it either.
Near the top of main, set each member of nums_form_mode to 0:
for(int a = 0; a < 50; a++)
nums_for_mode[a] = 0;
or, initialize it with ={0} at the declaration point. Fixing this will stop your segfault, but the program is still wrong:
You should also get the numbers in a loop, currently, your program only actually receives one number.
array[30] will be easy to overflow, including if you enter 30. You should make it one longer at least, and also check that the input actually is in range when reading it.
The function_called buffer is too small and prone to overflow, you should limit the size of input in the call to scanf.
this line: while (array[i2]!='\0') doesn't make much logical sense, it will terminate early without actually checking over the input.
Related
I am new to coding. As a practice problem, I wrote a program to sort strings as alphabetically, as in a dictionary. My program takes as input:
(a) The number of strings the user has in mind
and (b) The strings, one by one, each terminated by pressing the enter key.
It stores the initial input in a buffer array of size MAXSTR and simultaneously counts the number of characters. Then it creates allocates memory of requisite size at memory location input[i] and copies the buffer to that location. It also creates an index array, with array elements having value of 0, 1, 2 ... each corresponding to one the 0th string, 1st string, 2nd string ... and so on. The function dictsort sorts the index array based on the alphabetical position of the corresponding string.
My program runs smoothly on Linux machines. However, on Windows, it compiles alright, but while running the executable, it ends abruptly while executing the line "input[i]=(char)malloc(jsizeof(char));". If any of you guys can indicate what is happening it will be of great help. Note that my problem is with the main function only. The sorting functions work fine, and hence those are not either included or commented out from below code.
#define MAX 10000
#define MAXSTR 100
#include<stdio.h>
#include<stdlib.h>
//int dictsort(char **mainarray, size_t *indexarray, size_t elementcount);
//int strcompare(char* str1, char* str2);
//int getvalue(int input);
int main(void){
size_t n, i, j,k;
char buffer[MAXSTR];
int c;
size_t *index;
char **input;
printf("Input number of elements:\t");
scanf("%ld", &n);
n=n<MAX ? n : MAX;
index=(size_t*)malloc(n*sizeof(size_t));
getchar(); // flush the newline after scanf
for(i=0;i<n;++i){
index[i]=i;
printf("Input element %ld:\t", i+1);
j=0;
while(((c=getchar())!=EOF) && (c!='\n') && (c!='\0') && (j<MAXSTR-1)){
buffer[j]=c;
++j;
}
buffer[j]='\0';
printf("Upto 1\n"); //program comes upto here
input[i]=(char*)malloc(j*sizeof(char));
printf("Upto 2\n"); //never reaches here
for(k=0;k<j+1;++k){
input[i][k]=buffer[k];
}
}
//dictsort(input, index, n); //disabled for debugging
printf("The sorted array is: \n");
for (i=0;i<n;++i){
printf("%s ", input[index[i]]);
}
for(i=0;i<n;++i){
free(input[i]);
}
free(index);
return 0;
}
First error:
You are allocating memory for index and input[i], but not for input itself. This means that you are dereferencing an uninitialized pointer on the following line:
input[i]=(char*)malloc(j*sizeof(char));
This will invoke undefined behavior, which explains why it crashes on that line on one platform, but works on another platform.
Second error:
The line
input[i]=(char*)malloc(j*sizeof(char));
will not allocate sufficient space for storing the string. Since j is the size of the string without the terminating null character, you must allocate j+1 bytes instead.
Due to not allocating a sufficient number of bytes for the string, the following loop will access the memory buffer input[i] out of bounds:
for(k=0;k<j+1;++k){
input[i][k]=buffer[k];
}
This will invoke undefined behavior.
Third error:
Another source of undefined behavior in your program is the following line:
scanf("%ld", &n);
The correct conversion format specifier for size_t is %zu, not %ld. See the documentation of the function scanf for further information.
On 64-bit Microsoft Windows, a long has a width of 4 bytes, but a size_t has a width of 8 bytes. Therefore, because you are using the format specifier for long instead of size_t, the function scanf is probably only writing to half of the variable n, leaving the other half of the variable uninitialized. This is likely to cause trouble when you read the value of n later in the program.
Most compilers will warn you about using the wrong scanf conversion format specifiers, assuming that you enable all compiler warnings. You may want to read this:
Why should I always enable compiler warnings?
I'd like some assistance with understand how inputting data in a program of C works. So far I'm used the java syntax having the convenient try{}catch(){}; clause but I don't see it anywhere on C (or I haven't found it?).
Assuming I have the following array;
float f_array[10];
Normally for me to input data I'd either use a scanf(...); or a file which I can read input from, but for the shake of simplicity let's assume I use scanf(...);
And I have the following;
int i;
for(i = 0; i<10; i++){
scanf("%f", &f_array[i]);
}
Now , my question is how to restrain the user from putting in the input a character or a string or the wrong data type for that matter? Also , should I always try to initialize the array before actually putting values in it?
Note that scanf() returns number of elements successfully read, you can check it:
int success = scanf(...);
if (!success) {
scanf("%*[^\n]%*c"):
// OR while(getchar() != '\n');
}
There is, however, a complex solution. You don't use scanf(), but write a custom input method that processes keystrokes and filters out invalid characters, possibly using getch() (Windows/nCurses). Here's a minimized Windows version:
void readFloat(float* in){
int ch, ind = 0;
char buf[100];
while (1){
ch = getch();
if (ch >= '0' && ch <= '9' || ch == '.') {
buf[ind++] = (char)ch;
putchar(ch);
}
else if (ch == 8) /* Backspace */ {
printf("\b \b");
ind --;
}
}
buf[ind] = '\0';
float ret;
sscanf(buf, "%f", &ret);
return ret;
}
So a possible result of the code:
User input (key presses): 123aaa.bbb456
Program filter (displayed on screen): 123.456
Return value: (float)123.456
Now , my question is how to restrain the user from putting in the input a character or a string or the wrong data type for that matter?
Without dedicated hardware support (say, using a keyboard that does not have letter keys, or some device that gives the user an electric shock to discourage them from hitting the 'A' key) there is no way to restrain a user from entering unwanted data.
Instead, you need to write your code with the ASSUMPTION that the user will enter invalid or poorly formed data, and cope with that. It is true that your code is simpler if you can assume an obedient and tractable user who only gives correct input, but the real world isn't like that.
scanf() - reading and interpreting data directly from stdin doesn't actually work well with such an assumption. The return value from scanf() can give you an indication a problem after the fact (e.g. the return value is number of fields successfully input, or EOF). However, when a problem occurs, scanf() handles it in a way you cannot control. Let's say you code has a
scanf("%f", &f_array[i]);
and the user hits the 'X' followed by the Enter key. scanf() will recognise the 'X' character is waiting to be read, and return immediately. The value it returns will not be 1 (which would indicate success). Even worse, the 'X' will be left to be read by a subsequent call of scanf() and the same will happen again (unless a different format is specified). Which means, if you call scanf() in a loop this way, the same will happen over and over again.
Some folks will tell you to simply find a way to read and discard the character 'X'. The problem with that approach is that there are MANY ways for the user to enter bad inputs, and you need to account for all of them. If the user does something you (or your code) doesn't expect, you get problems (e.g. program hanging waiting for the same input repeatedly, input being used as data when it isn't). You're back where you started.
The more robust approach is to simply read a line of input, and do checks before trying to extract a floating point value from it, such as
char buffer[20];
int got_one = 0;
while (!gotone && fgets(buffer, sizeof buffer, stdin) != NULL)
{
if (check_string(buffer))
{
if (sscanf(buffer, "%f", &f_array[i]) == 1)
{
/* yay - we got a floating point value */
got_one = 1;
}
else
{
fprintf(stderr, "Floating point scanning failed. Try again\n");
}
}
else
{
fprintf(stderr, "Bad data discarded. Try again\n");
}
}
Essentially, this provides several hooks so you can check user input in various ways. If you want to, it can be adapted to discard part of a line, and scan useful data from whatever's left.
The key, however, is that the code does not assume the user is well behaved. It only attempts to read a floating point value after a gauntlet of checks, and still copes if the reading fails.
The code can also be adapted to deal with users who enter data that overflows the buffer (e.g. entering 30 floating point characters on a single line). I'll leave that as an exercise.
Also , should I always try to initialize the array before actually putting values in it?
That depends on the needs of your code, but generally speaking I would not bother.
With approaches like I suggest above, you can avoid a circumstance of using the array (or elements of the array) unless valid data has actually been put into it.
All initialising the array will do is obscure cases where the code doing input (reading from the user) has not properly dealt with bad user input.
give the user some feedback on a per input basis.
process each input and allow user to make corrections as you go.
use "atof()" to do the conversion, but it has a couple of quirks:
it tells you there is an error by returning a value of 0.0
it stops processing if/when it finds an invalid char and returns what it has up to that point
eg. 6.35k gives 6.35 -- this usually works out ok;
otherwise you have to check for invalid chars yourself.
try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
float f_array[10];
int i;
float input_value;
char temp_string[32];
for(i = 0; i<10; i++){
printf("input a floating point number: ");
scanf("%s",&temp_string[0]);
input_value = atof(temp_string);
while(input_value == 0.0) {
printf("%s is not a valid floating point number\n");
printf("example is 5.6 or 1e32 or 17\n");
printf("try again - input a floating point number: ");
scanf("%s",&temp_string[0]);
input_value = atof(temp_string);
}
f_array[i] = input_value;
printf("String value = %s, Float value = %f\n", temp_string, input_value);
}
/* use the data */
for(i = 0; i<10; i++){
printf("%f\n",f_array[i]);
/* do something */
}
}
I've been doing some exercise with structures to prepare for my upcoming exams, and I've run into a bit of trouble with this code.
// Creates a structure of type 'person' with a first name (nameF), last name (nameL), and the age (age)
typedef struct {
char nameF[20];
int age;
char nameL[40];
}person;
// Main function
int main() {
person ppl[2]; // We are creating 3 "people", whose information shall be printed into the file
// This loop takes user input to create the names and ages of 3 people
int i;
for (i = 0; i <= 2; i++) {
printf("\nEnter first name %d: ", i+1);
scanf("%s", &ppl[i].nameF);
printf("%s\n", ppl[i].nameF);
}
printf("It worked\n");
system("pause");
return 0;
}
It runs fine, but when the program exits, I keep receiving an error message from the Debugger that states: "Run-Time Check Failure #2. Stack around the variable 'ppl' was corrupted."
So I looked it up on Stack Overflow, this error appears when you go outside the bounds of a string. I don't understand where in my code I'm going out of bounds.
Here's an example of the output:
Enter first name 1: 'Adolfo'
Adolfo
Enter first name 2: 'Cecilia'
Cecilia
Enter first name 3: 'Tim'
Tim
Press any key to continue...
And then the error message pops up.
As you can see none of my inputs exceed the maximum amount of characters for the variable 'nameF', so there should be no reason for me to receive the error.
I saw someone on Stack Overflow mention that instead of making a character array:
char nameF[20];
One should instead write use dynamic memory allocation:
char * nameF = malloc(<enough bites to support any input);
Unfortunately, I don;t quite have a grasp of memory allocation yet, and when I attempted this code, I received all sorts of other errors, and my program wouldn't even run.
What is the mistake?
Also, I am not sure if this information is important, but I wrote this code using Visual Studio in C.
Edit: "char * nameF[20]" to "char nameF[20]" that asterisk was a leftover from my previous attempts at fixing the code, sorry.
Why are you allocating two structures then filling it with three responses?
Also, scanf is very dangerous as it can easily be abused to overwrite past a buffer. Look for routines (or write one) that limits the input to the length of the string.
hint: scanf man page might lead you to a better version.
Not meant as an answer, just made some adaptions allowing you to continue your work:
typedef struct {
char nameF[20]; // may take on 19 characters (+ string terminating char)
int age;
char nameL[40];
}person;
int main() {
person ppl[3]; // 3, not 2.
int i;
for (i = 0; i <= 2; i++) {
printf("\nEnter first name %d: ", i+1);
scanf("%s", ppl[i].nameF); // removed the &
printf("%s\n", ppl[i].nameF);
}
printf("It worked\n");
system("pause");
return 0;
}
I am new to programming in C and still trying to learn all of the useful functions it provides in its libraries. In particular I'm trying to wrap my head around how to use getchar() for more than one character in a certain situation. I want to be able to have input from the console be something like:
11 2 34 100
I want to be able to distinguish between these entries(delimiter space I guess?), and add these numbers up. This is an assignment, so I was wondering if someone could give me a hint or point me in the right direction on how to go further with this. I would certainly appreciate it. This is what I have at the moment. Also, we're not supposed to make use of arrays here. This really threw me because I don't see any other way. Again any help or pointers in the right direction would go a long way!
int main()
{
int count = 0;
char input;
int wordCount = 0;
int numEntered = 0;
input = getchar();
while(input != '\n')
{
if(input != ' ')
{
count++;
}
input = getchar();
}
printf("Number of characters included in numbers %d\n", count);
return 0;
}
You can store two integers, one that is the running total, and one that is the current number.
If you encounter a digit that is not a space, multiply the current number by 10 and then add that digit to the current number.
If you encounter a space, add the current number to the running total, then reset the current number to 0.
I need to limit the input from a user to only positive values, and count the number of digits in that number. The user will only type in a (+/-) whole number up to 9 characters long.
I'm only allowed to use the scanf function and for, while, or do-while loops.(I saw in similar questions how to do this using getchar, but I can only use scanf). I'm not allowed to use arrays, or any other library besides stdio.h and math.h
I know that if I write:
n=scanf("%c%c%c%c%c",&a,&b,&c,&e,&f);
n will count the number of successful scanf conversions.
The problem i'm having is that when I define the input with char, it does everything I want except that the user MUST enter 5 characters. So if the user wants to input "55" he has to press "5" "5" "enter" "enter" "enter".
I need the program to move on after the first "enter" but also be flexible to receive a number up to 9 digits long.
again, I can't use getchar or anything fancy. Just the really basic stuff in C that you learn in the first 2 weeks.
Use scanf to read the number into a long int , then use a for loop with a /10 to count the number of digits
What do you want the program to do in case of a -ve number being entered?
#include<stdio.h>
int main()
{
long int a;
int b;
do
{
scanf ("%ld",&a);
if(a<0)
printf ("invalid input");
}while(a<0);
for(b=0;a!=0;b++,a=a/10);
printf("%d",b);
}
(does not handle -ve numbers specially)
Something like
#include <stdio.h>
int main(void)
{
char buffer[10] = { 0 };
size_t len;
scanf("%9[0-9]", buffer);
for(len = 0; buffer[len] != 0; len++) ;
printf("%zu '%s'\n", len, buffer);
return 0;
}
works, but I don't know if it fits your need.
EDIT (bits of explanation)
You can replace size_t with int (or unsigned int), though size_t is better. If you do, use %d or %u instead of %zu.
The basic idea is to exploit a feature of the format of scanf; the 9[0-9] says the input is a sequence of up to 9 char in the given set i.e. the digits from 0 to 9.
The for(...) is just a way to count char, a simple implementation of a strlen. Then we print the result.
The approach I would take would be the following.
Loops are allowed, so go ahead and set one up.
You need to have a variable somewhere that will keep track of what the current number is.
Think about typing out a number, one character at a time. What needs to happen to the current_number variable?
You need to stop the loop if a return key has been pressed.
Something like this should do for starters, but I'll leave the rest up to you, specifically what return_check(ch), update_state(current_val) and char_to_int(ch) looks like. Also note that rather than use a function, feel free to put your own function directly into the code.
int current_val=0;
int num_digits=0;
char ch="\0"
for (num_digits=0;return_check(ch) && num_digits<=9;num_digits++)
{
fscanf("%c");
current_val=update_state(current_val);
current_val=current_val+char_to_int(ch);
}
As for the logic in update_state(), think about what happens, one character at a time, if a user types in a number, like 123456789. How is current_val different from a 1 to a 12, and a 12 to a 123.
Can you wrap a loop around it, something like (I don't know if all of the syntax is right):
const int max_size=9
int n=0; //counter for number of chars entered
char a[max_size-1];
do {
scanf(%c,&a[n]);
n++;
} while (a[n] != '\r' && n<max_size)