I keep getting a sementation fault when compiling and running my code - c

I know it means that there is a problem with trying to access restricted memory but I do not know how to find where the error is occurring or how I would go about fixing it. An small explanation would be very helpful.
int main(int argc, char* argv[1]) {
char emptyBoard[3][3];
char player;
int row, column; // moves
int i, j;
// int x = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
emptyBoard[i][j] = '.';
}
}
/*
for(i = 0; i < 3; i++){
for (j = 0; j < 3; j++){
printf("%c ", emptyBoard[i][j]);
}
printf("\n");
}
*/
FILE* filePtr = fopen(argv[1], "r");
if (filePtr == NULL) {
printf("Cannot open File \n");
return 1;
}
while (fscanf(filePtr, "%c, %d, %d", &player, &row, &column) != EOF) {
// moves = x++;
emptyBoard[row][column] = player;
printBoard(emptyBoard);
}
// printf("Total Moves: %d", moves );
fclose(filePtr);
}
void printBoard() {
int i, j;
char array[3][3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf("%c ", array[i][j]);
}
printf("\n");
}
}

I know this isn't what you asked for, but I noticed you're passing a variable to printBoard in printBoard(emptyBoard), but the function does not actually take any arguments. What will be printed here is a 'random' collection of values.
As for what you asked, do you pass any arguments to your executable? If it's titled 'run' for example, do you type ./run file.txt or just ./run? If you are doing the latter, that will cause a Segmentation fault because you are trying to load in a value that was not allocated to the argv. Allan is also correct, if the file you are loading calls higher row or column than 3, segmentation fault occurs because you are trying to access memory that you did not allocate to emptyBoard.
As to finding the cause of runtime errors, I have found placing print statements at the different steps of my program to be quite helpful. You could learn to use a debugger.

The program crash if row or column in input file is >= 3.
The fscanf condition is not sufficient to terminate the loop either check on number of records have been processed or add space so scanf eats the trailing newline:
while (fscanf(filePtr, "%c, %d, %d ", &player, &row, &column)) != EOF) {
You call printBoard(emptyBoard) but it's defined as not taking any arguments, and you create a local array. Try this instead:
void printBoard(size_t row, size_t column, char array[row][column]) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
printf("%c ", array[i][j]);
}
printf("\n");
}
}
...
printBoard(3, 3, emptyBoard);
This will result in players being accumulated. If you want one player per board, then you need to either initialize the board or operate on a copy of empty board:
char board[3][3];
memcpy(board, emptyBoard, sizeof(emptyBoard);
board[row][column] = player;
printBoard(3, 3, board);

Related

Get several characters lines into an array in c

for an uni assignment I have to do the following: https://ibb.co/5WpMS0V (I cant upload a photo, the server is messed up or something)
What I've got so far is the following: Im trying to get all the characters that I need to put in, into an array but it's not working properly. Can anyone explain to me how to do this? Also, the subject this week is recursion, so I should make this with the use of recursion. If anyone knows how to get the characters in properly, then I know how to move on! Thanks in advance.
// libraries
#include <stdio.h> // endables input/output commands
#include <stdlib.h> // enables standard library of functions
// main
int main(int argc, char *argv[]) {
int numberOfRows;
int numberOfColoms;
scanf("%d %d", &numberOfRows,&numberOfColoms);
char matrix[numberOfRows][numberOfColoms];
char letter = getchar();
scanf("%c" , &letter);
do {
for (int i = 0; i < numberOfRows; i++) {
for (int j = 0; j < numberOfColoms; j++) {
scanf("%c" , &matrix[i][j]);
}
}
} while (letter != '\n');
for (int i = 0; i < numberOfRows; i++) {
for (int j = 0; j < numberOfColoms; j++) {
printf("%c" , matrix[i][j]);
}
}
return 0;
}
The letter variable and the do .. while loop are unnecessary. You just need to read rows * cols characters.
Use " %c" with scanf to skip leading whitespace when reading a character. This will have the effect of ignoring the newlines that separate each line of input.
Remember to check the return value of scanf, which is the number of successful conversions, so that you do not operate on bad data.
Consider limiting the values of rows and cols to an appropriate range. Currently negative or excessively large values will have adverse effects.
Note that the use of recursion is likely expected for the rest of the task (solving the word search), not populating your matrix.
Keep in mind, the contents of matrix are not strings - they are not null-terminated. Use of <string.h> functions and similar will surely lead to undefined behaviour.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int rows;
int cols;
if (2 != scanf("%d %d", &rows, &cols)) {
fprintf(stderr, "Failed to read rows and columns.\n");
return EXIT_FAILURE;
}
char matrix[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (1 != scanf(" %c" , &matrix[i][j])) {
fprintf(stderr, "Unexpected end of valid input.\n");
return EXIT_FAILURE;
}
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%c" , matrix[i][j]);
}
putchar('\n');
}
}

Read words from keyboard into a C 2D array

I would need some help after googling like 2 hours with no luck. (Maybe i'm just formulating my question incorrectly?)
I need to read 10 words from keyboard, and show a warning if any of the last 9 words are bigger than the first word.
I know how to use strlen to determine the last part of the request, but I have no idea how to do the first one.
My code looks like this:
const int ARRAY_SIZE = 10;
const int MAX_WORD_SIZE = 101;
int main() {
char arr[ARRAY_SIZE][MAX_WORD_SIZE];
for (int i = 0; i < ARRAY_SIZE; ++i) {
for (int j = 0; j < MAX_WORD_SIZE; ++j) {
printf("Add word %d:\n", i+1);
scanf("%s", arr[i][j]);
}
}
return 0;
}
But it does not work. cLion tell me "Format specifies type 'char *' but the argument has type 'int'".
I really don't understand why this doesn't work.
"%s" expects a memory address to where it is supposed to start saving the string.
You have a two dimensional array arr[ARRAY_SIZE][MAX_WORD_SIZE];. When you use [] once you get a 1-dimension array, which is what %s expects.
But since you are using [] twice, you are getting a single element of that array type, which is char.
change your scanf to: scanf("%s", arr[i]); to fix that.
Having noticed that, you can get rid of the inner for loop and variable j.
for (int i = 0; i < ARRAY_SIZE; ++i) {
printf("Add word %d:\n", i+1);
scanf("%s", arr[i]);
}
The solution to your problem would be:
const int ARRAY_SIZE = 10;
const int MAX_WORD_SIZE = 101;
int main() {
char arr[ARRAY_SIZE][MAX_WORD_SIZE];
for (int i = 0; i < ARRAY_SIZE; ++i) {
printf("Add word %d:\n", i+1);
scanf(" %s", arr[i]);
}
return 0;
}
It is a good practice to put a blank space in " %s". This way, chars such us \n are ommited, and many problems which stem from here are avoided.
If you wanted to do
for (int i = 0; i < ARRAY_SIZE; ++i) {
for (int j = 0; j < MAX_WORD_SIZE; ++j) {
printf("Add word %d:\n", i+1);
scanf("%s", arr[i][j]);
}
}
you would be reading character by character, so you would have to do instead:
for (int i = 0; i < ARRAY_SIZE; ++i) {
for (int j = 0; j < MAX_WORD_SIZE; ++j) {
printf("Add word %d:\n", i+1);
scanf("%c", arr[i][j]);
}
}
This way of solving the problem may give rise to another problem: not all words have the maximum size so this would be fixed by:
for (int i = 0; i < ARRAY_SIZE; ++i) {
for (int j = 0; j < MAX_WORD_SIZE; ++j) {
printf("Add word %d:\n", i+1);
scanf("%c", arr[i][j]);
if(arr[i][j]=='\n'){
break;
}
}
}
Anyway, the first one is the best solution.

How to implement check for distinctness

I have a function that reads in a line of ints as an array. I would like to implement an additional check for distinctness in the elements. I am already checking to make sure the array values don't equal the element number.
I tried nesting another for loop to run the check within the other check but I couldn't get it to work properly.
int readArray(int r[SIZE]) {
int i;
for (i = 0; i < SIZE; i++) {
scanf("%d", r + i);
// check for error element number
if (i == r[i]) {
printf("Error: element[%d] == %d\n", i, i);
return 0;
}
}
return 1;
}
I expect the function to output an error if there is a duplicate value or if the element number and value are equal.
My working solution is listed below I would like to make it a bit more concise is possible.
int i,j;
for (i = 0; i < SIZE; i++) {
scanf("%d", r + i);
// check for error
if (i == r[i]) {
printf("Error: Element[%d] == %d\n", i, i);
return 0;
}
}
// check for distinctness
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
if(i != j)//check indexes
{
if (r[i] == r[j])
{
printf("Two elements repeat to %d" , i);
printf("\nBad input exiting program");
return 0;
}
}
}
}
return 1;
}
Maybe it's not more concise, but if you want something more efficient, how about this:
...
for (i = 0; i < SIZE; i++)
{
for (j = i; j < SIZE; j++)
...
That way, you skip the comparisons you already made ;)
EDIT: Oh, even better:
...
for (j = i+1; j < SIZE; j++)
...
That way, you get rid of the:
if(i != j)

Segmentation failure

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int score,i,j;
int *ptr, *ptr1;
int over;
printf("Enter the number of over");
scanf("%d",&over);
ptr=(int*)malloc(over*sizeof(int));
// do the iteration, outer for loop, read row by row...
for(i=0; i <= (over-1); i++)
{
printf("%d%d ", i, ptr[i]);
// inner for loop, for every row, read column by column and print the bar...
printf("Enter the number of run per over");
scanf("%d",&score);
ptr1=(int*)malloc(score*sizeof(int));
for(j = 1; j<= ptr1[i]; j++)
// print the 'bar', and repeat...
printf("|");
// go to new line for new row, and repeats...
printf("\n");
}
return 0;
}
You are using
ptr1=(int*)malloc(score*sizeof(int));
inside your for loop. That causes memory leak. You should free the memory.
You also have
printf("%d%d ", i, ptr[i]);
But ptr[i] has not been assigned any value, so it just gives garbage value. The same problem occurs in
for(j = 1; j<= ptr1[i]; j++)
So you need to assign some value to them before using them like this.
Casting the result of malloc doesn't make any sense, it is pointless and potentially bad practice.
printf("%d%d ", i, ptr[i]);. You print the value of an uninitialized memory cell. This is undefined behavior and might in theory cause the program to crash on some platforms. If you need the memory allocated to be initialized to zero, you should be using calloc() instead.
ptr1=(int*)malloc(score*sizeof(int)); for(j = 1; j<= ptr1[i]; j++) This code makes no sense whatsoever and will crash the program. You use ptr1 as if it was an initialied array of integers, while it is actually an uninitialized, single integer.
#include <stdio.h>
#include <stdlib.h>
int main(void){
int **scores;
int over, score;
int i, j;
printf("Enter the number of over : ");
scanf("%d", &over);
scores = (int**)malloc(over*sizeof(int*));
for(i = 0; i < over; i++){
printf("%d ", i + 1);
printf("Enter the number of run per over : ");
scanf("%d", &score);
scores[i] = (int*)malloc((score+1) * sizeof(int));// +1 for number of columns
scores[i][0] = score;
for(j = 1; j <= score; j++){
printf("%d Enter the score : ", j);
scanf("%d", &scores[i][j]);
}
}
for(i = 0; i < over; i++){
for(j = 1; j <= scores[i][0]; j++){
printf("|%d", scores[i][j]);
}
printf("|\n");
}
//deallocate
for(i = 0; i < over; i++)
free(scores[i]);
free(scores);
return 0;
}

Need explanation for odd for loop/scope problem

While starting on a program for getting a matrix's Reduced Row Echelon Form, I transferred my code for printing the array into its own function. As soon as I did this, I got a segfault. What puzzled me though, was the fact that an unrelated variable declaration (commented below) solved the segfault.
#include <stdio.h>
int COLS = 3;
int ROWS = 3;
void PrintArray(int array[][COLS]);
int main (int argc, char**argv) {
int i, ii = 0;
FILE *file;
file = fopen(argv[1], "r");
int array[ROWS][COLS];
fscanf(file, "%d %d", &ROWS, &COLS);
while (!feof(file))
{
fscanf(file, "%d", &array[i][ii]);
ii++;
if (fgetc(file) == '\n') {
i++;
ii = 0;
}
}
int j = 0, k = 0; //This solved the segfault.
PrintArray(array);
printf("\n");
fclose(file);
return 0;
}
void PrintArray(int array[][COLS]) //The printing function
{
int j, k;
for (j = 0; j < ROWS; j++)
{
for (k = 0; k < COLS; k++)
{
printf("%d", array[j][k]);
}
printf("\n");
}
}
After a couple hours of debugging, I eventually figured out that it may have had something to do with the scope of the variables within the for loop.
To illustrate:
int COLS = 3;
int ROWS = 3;
int a; //declared globally
//main
for (a = 0; a < ROWS; a++) {
printf("for loop");
}
works, but as soon as I declare "a" in main:
int COLS = 3;
int ROWS = 3;
//main
int a; //declared in main
for (a = 0; a < ROWS; a++) {
printf("for loop");
}
it doesn't work.
Also, if I replace the global variables with numbers, I still get a segfault, until I remove the line which originally fixed the segfault!
void PrintArray(int array[][3]) //COLS
{
int j = 0, k = 0;
for (j = 0; j < 3; j++) //ROWS
{
for (k = 0; k < 3; k++) //COLS
{
printf("%d", array[j][k]);
}
printf("\n");
}
}
This appears to be as far as I can get to understanding the problem, so your help would be appreciated.
You are getting out of array bounds. The two extra variables lay right after the array on the stack, so you begin corrupting them instead of something else, that's why segfault is “solved” (it's not solved, of course, the bug is still there).
There are severe problems with that code:
Variable i is used without being initialized
The array size is always 3x3. Reading new values for ROWS and COLS does NOT resize the array. If e.g. you have read ROWS=4 and COLS=4 from file, you will corrupt the memory outside of that allocated for array.

Resources