Printing from a file and storing in arrays. [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Im trying to read from a file into an array, which is shown in the first for loop. This part of my script works, however i want the answers that the user gives to be copied into the array q.a in the q structure. and the at the end of the script the questions and answers given printed off. Can anyone shed some light on why this isn't working for me?
struct qa{/
char q[40][250];
char a40][250];
};
int main()
{
int a, i, k, l, j;
FILE *fp;
fp = fopen("quest.txt", "r");
struct qa q;
for(i>0;i<=11;i++){
fgets(q.q, 250, (FILE*)fp);
printf("%s", q.q);
scanf("%s", q.a[l][j]);
}
for (i=0;i<11;i++){
strncpy(q.a[j], q.q[k], 250);
}
for (i = 0; i < 11; i++){
printf("%s/n", q.a[l][j]);
}
I get a segmentation fault error when i try and run the script that only started happening when i put the strncpy for loop in.

First of all you never initialize your values : i j k l are never initialized and a isn't even used.
Then you're trying with scanf("%s", q.a[l][j]); to put a char * into a char.
See stacktrace
For debugging purposes install and use valgrind/gdb if you're into cli or any debuggers in your IDE, it will be easier
This is the code I used, if you want to know which lines point to which line of code
Change scanf("%s", q.a[l][j]); to scanf("%s", q.a[l]); and do the same for the last printf
Also remember to compile with flags like -W -Wall -Wextra so that you can get more warnings from the compiler, it can detect most of your mistakes.

This is awful:
for(i>0;i<=11;i++){
fgets(q.q, 250, (FILE*)fp);
printf("%s", q.q);
scanf("%s", q.a[l][j]);
}
with one inconsistency per line!
for(i>0;i<=11;i++) the first element of a for is for assignation so it should never contain a comparison. You want for(i=0; i<11; i++)
fgets(q.q, 250, (FILE*)fp); - q.q is an array of char arrays, when what is expected by fgets is an array of characters. It should be fgets(q.q[i], 250, (FILE*)fp);.
printf("%s", q.q); invokes undefined behaviour, because q.q is an array of array of chars when %s expects a char pointer. It should be printf("%s", q.q[i]);
scanf("%s", q.a[l][j]); %s expects a pointer to an array of characters, and you give it the value of a single character! What you want is scanf("%249s", q.a[i]);
This means nothing:
for (i=0;i<11;i++){
strncpy(q.a[j], q.q[k], 250);
}
j and k are uninitialized automatic variables, so their value is anything. In short you are writing random values at random memory location!
Even the last part is poor:
for (i = 0; i < 11; i++){
printf("%s/n", q.a[l][j]);
}
l is still uninitialized, the end of line is \n with a backslash and not a straight slash, and %s still expects a char pointer... If you want to print the questions and answers, just do:
for (i = 0; i < 11; i++){
printf("%s\n%s\n\n", q.q[i], q.a[i]);
}
it will give you the question on a line, the answer on the following one, and the empty line before next bloc.
TL/DR: you really should consider learning the basics of C language...

Related

please help me to find the error in this C code [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am a beginner to c language. Please help me to find the error of the code as it gives a complilation error on the display.
#include <stdio.h>
#include <string.h>
void main()
{
char i;
char arr[23];
printf("Enter your name? \n");`
scanf("%c",&arr[i]);
for(int v=0;v<=strlen(arr);v++)
{
printf("%c",arr[v]);
}
}
Your code has several issues, not only one:
1.
You use the wrong format specifier %c to catch a single character instead of %s to catch a string:
char arr[23];
printf("Enter your name: \n");`
scanf("%c",&arr[i]);
Rather use scanf("%s",arr); or even better scanf("%Ns",arr); where N stands for the maximum number of characters to be entered. Note that you need one element for the string-terminating null character, so it requires to be at least one character less than the char array is consisted of.
You can also use fgets(arr,23,stdin) which is preferred for consuming strings from the standard input because it is more safe as it requires you to provide the maximum amount of characters to read (counting the null character too) and also reads white space separated words as part of the string by default.
2.
i is not initialized to any value, so:
scanf("%c",&arr[i]);
causes undefined behavior.
3.
Furthermore you try to get a string length by using strlen() as part of the condition expression of the for loop:
for(int v = 0; v <= strlen(arr); v++)
although there is no valid string in arr which causes also undefined behavior.
As a side note here: It is more efficient to use strlen() only once before the for loop, store its return value in an object of an appropriate type (size_t is the type of the return value of strlen()) and use that object in the condition of the for loop instead of executing strlen() before each iteration.
4.
Next thing is that you attempt to print characters inside the for loop which arenĀ“t provided/initialized to arr:
for(int v = 0; v <= strlen(arr); v++)
{
printf("%c",arr[v]);
}
5.
The for loop with the condition v <= strlen():
for(int v = 0; v <= strlen(arr); v++)
runs one time more than expected and prints the null character which is redundant since the null character is not printable.
Rather use v < strlen() or according to point 3:
size_t len = strlen(arr);
for(int v = 0; v < len; v++)
6.
The return value of main shall be int, not void.
7.
There is a trailing apostrophe after the printf() call:
printf("Enter your name: \n");`
Rather use:
#include <stdio.h>
int main()
{
char arr[23];
printf("Enter your name: \n");
scanf("%22s",arr);
printf("%s",arr);
}
Online Example
if you want to print out the string entered as whole at once, or:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[23];
printf("Enter your name: \n");
scanf("%22s",arr);
size_t len = strlen(arr);
for(int v = 0; v < len; v++)
{
printf("%c",arr[v]);
}
}
Online example
if you want to print each character separate.
Your error is not really an error. You have an extra character in this lane:
printf("Enter your name? \n");`
It should be:
printf("Enter your name? \n");
There is a ` at end of the line
printf("Enter your name? \n");`
note you are using uninitialized int i here scanf("%c",&arr[i]); which is wrong.
also with scanf("%c",&arr[i]); you can only scan one character for string arr which I think is not your purpose.
you can use scanf("%s",arr[i]); instead to appropriately scan an string .
also note when ever you are scanning string char by char you have to add terminator \0 to the end of your string.after scanning characters until element i-1 of array add \0 to element i like this arr[i]=\0;.
since your string isn't terminated appropriately strlen won't work well.
also note you should print elements of string while v<strlen(arr) the last char should be \0 so you should use in for(int v=0;v<=strlen(arr);v++)
also pay attention to use int main not void main.
look:
void main()
{
char arr[23];
printf("Enter your name? \n");
scanf("%s",arr);
for(int v=0;v<strlen(arr);v++)
{
printf("%c",arr[v]);
}//or instead of loop use printf("%s",arr);
}

Trying to return the char in the middle of an input (char array) gives "segmentation fault (core dumped)"? [duplicate]

This question already has answers here:
Why does C's printf format string have both %c and %s?
(11 answers)
Closed 4 years ago.
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!
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!
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.
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
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:
gets the size of 1st variable ("Hello")
gets the size of 2nd variable (name) How? Simple by this loop:
int varSize;
for (varSize = 0; varSize != '\0'; ++varSize);
moves "Hello" into buffer
Determine the size of second parameter. How, by doing this:
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.

pointer and char array [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am using gcc 4.9.2-10 deb8u1 compiler to compile
Here is my code
#include <stdio.h>
int main(){
char *s;
char sa[10] , sb[10];
scanf("%s", sa);
printf("line\n");
scanf("%s", sb);
printf("%s %s", sa, sb);
}
Above code is no any problem if char is under the space provided
However
scanf("%s", s);
printf("line\n");
scanf("%s", sa);
printf("%s %s", s, sa);
Input:
$:
Hu
Result:
line
(null) Hu
Someone could told me what happen about second code wrong .?
I cannot figure out why i cannt input second one .. Thx a lot .!
In you code
char *s;
char sa[10] , sb[10];
you can't do much with s.
scanf("%s", sa);
is ok, provided the input fits. You can jump through a few hoops, reading the inputs in chunks in a loop if it might be longer (see here)
However, in you "However" section of the question you try
scanf("%s", s);
Since s doesn't point to memory - you'd need to have allocated some - you have undefined behaviour, so anything could happen.
I cannot figure out why i cannt input second one ? because s is not initialize and not having any valid address & doing scanf() on that results in undefined behaviour.
First allocate the memory and then scan the user input.
int main() {
char *s; /* its un initialized */
s = malloc(size); /* this you need to do ? specify the size value */
fgets(s,size,stdin);/* its advisable as its not having overflow problem */
printf("%s\n",s);
/* once job is done , free it by calling free(s) */
free(s);
return 0;
}
Use fgets() instead of scanf() to scan the user input for the reason listed in comments.

What's wrong with my c code? (it's probably the malloc call) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
When I run this code, I get a segmentation fault. I'm sure I'm doing the pointers wrong, but I'm not sure why or how to fix it.
I also included the question I'm trying to answer in picture form.
#include <stdio.h>
#include <stdlib.h>
char * repeat_characters(char *s, int n) {
printf("%s", *s);
char temp;
int length = 0;
int i = 0;
int j = 0;
int k = 0;
char * newString;
while(s[length]) {
length++;
printf("%d", length);
} // finds length of string
newString = (char*) malloc(length*n*sizeof(char));
while(i++ < i*n) {
temp = s[i];
while (j++ < n) {
newString[k] = temp;
printf("%c", temp);
k++;
}
}
printf("%s", newString);
return newString;
}
int main () {
char * string[100];
int numReps = 0;
printf("Enter a string: ");
scanf("%s", string);
printf("\nEnter number of repetitions: ");
scanf("%d", &numReps);
repeat_characters(*string, numReps);
return 0;
}
One of your jobs as a questioner is to shorten your program to the minimum that demonstrates a problem. For instance, the following would give a segmentation fault:
#include <stdio.h>
char * repeat_characters(char *s, int n) {
printf("%s", *s);
return NULL;
}
int main () {
char * string[100];
scanf("%s", string);
repeat_characters(*string, 0);
return 0;
}
Lots of kinds of problems could be pointed out by compiler warnings. So turn those warnings on. If you're using gcc, then try something like gcc -Wall -Wextra -Werror main.c (or look in your compiler's documentation.)
(The -Werror will turn the warnings into errors, and keep you from accidentally ignoring a warning, which I'd say is a good habit for both learners and experts alike.)
printf("%s", *s);
format '%s' expects argument of type 'char*', but argument 2 has type 'int'
Here you have a parameter char *s. Depending on context could either be a pointer to a single character, or a pointer to the first character of a multiple-character sequence.
C strings operate on the convention that it's a multiple character sequence, and that the range of characters is eventually terminated by a '\0' (or 0-valued character). So when you call printf you must be sure that the character pointer you pass in is to such a validly formed sequence.
You are passing in *s, which dereferences the pointer-to-a-character to make it into a single character. If you want to print a single character, then you'd need to use %c, e.g. printf("%c", *s);. But you want to print a C string, so you should drop the dereferencing * and just say printf("%s\n", s). (You will likely want \n to output a newline, because otherwise your prints will all run together.)
(Note: The reason C without warnings didn't complain when you passed a character where a character pointer was expected is due to the "weirdness" of functions like printf and scanf. They don't have a fixed number or type of arguments that they take, so there is less checking...warnings help pick up the slack.)
scanf("%s", string);
format '%s' expects argument of type 'char*', but argument 2 has type 'char**'
Here you have the problem that you've declared s as char * string[100];, which is an array of character pointers, not an array of characters. The duality of a C array being able to behave like a pointer to its first element takes some getting used to, but if you say char string [100]; then string[0] is a char and string can "decay" to a char* synonymous with &string[0]:
Is an array name a pointer?
while(i++ < i*n)
operation on 'i' may be undefined
The compiler is making a technical complaint here, about modifying the variable i in an expression that also uses i. It's warning about whether the i in i*n would see the value before or after the increment. Avoid this kind of expression...and when-and-if the time comes where you care about what you can and can't do like this, read about sequence points.
But put that aside. What did you intend here? Take the nuance of ++ out of it...what about just while (i < i * n)? When would that be false? Why would it be relevant to solving the problem?
Look through your code and perhaps try commenting it more. What are "the invariants", or the things that you can claim about a variable that would be true on each line? If you were asked to defend why the code worked--with no compiler to run it to see--what would be giving you the certainty that it did the right thing?
Then step through it with a debugger and examples, and check your intuition. If you step over a line and don't get what you expect, then that's when it may be time to start thinking of a question to ask which draws the focus to that line.
There's other issues raised in the comments (for instance, that your malloc() doesn't include space for the terminator, and even once you add in 1 for that space you still have to write a '\0' into it...). Generally speaking your program should perform as many free()s as it does malloc()s. Etc. But hopefully this points you in the right direction for the assignment.

read csv file into 2-d array in c

I'm not familiar with C at all. I just need to input my data into an already well-developed model in C, put the data in arrays, get my output and put that output back into my program in Python. My data is in a CSV file and I'm just trying to put it in a 2-D array to run through some functions. When I run the following code to make sure I created my array, I get a random single value in the output that does not match the original data at all. Sometimes it prints 0.00000. I'm trying to view the entire array to make sure it's ready to be input.
Also, this is just a sample; my real data set will have >3000 rows. I understand I will need to use malloc() for this when I run my real data, correct?
#user3629249 thank you and #Cool Guy for all your comments. Here's what I have now. I think sprintf() is still having trouble converting my array values back to a float. I've searched all over and I still cant tell what I doing wrong but the error is telling me that data[l][k] and todata are still incompatible, could you tell me if I'm on the right track and what I'm doing wrong with the sprintf() function?
#include <stdio.h>
int main() {
FILE *fp;
fp=fopen("airvariablesSend.csv", "r");
if(fp == NULL){
printf("cannot open file\n\n");
return -1;
}
// Headers removed for simplicity. Still found in airvariables.csv to see which //column means what
float data[9][6]; //for putting into array
int k , l;
float num; //for using getline() function
char *memory;
int nbytes = 500;
// space for using malloc? Is this enough or too much?
char *token; //for parsing through line using strtok()
char *search = ","; //delimiter for csv
char *todata; //for
//asking for space on heap
memory = (char *) malloc (nbytes + 1);
// Don;t need to use realloc() because getline() does it automatically? //http://crasseux.com/books/ctutorial/getline.html
for(k = 0; k < 6 ; k++) //repeats for max number of columns
{
for (l=0; l< 9; l++) //modify for number of rows that you have
{
num = getline (&memory, &nbytes, fp); //reading line by line
token = strtok(num, search); //separating lines by comma in csv
//Apparently strtok() will only use whitespace and I'm getting warnings here too. Is there another function for separating by commas?
sprintf(todata, "%f", token);
data[l][k] = todata;
printf("%f\n", data[l][k]);
}
}
fclose(fp);
free(memory);
return 0;
}
Change
for (l=1; l< 11; l++)
To
for (l=0; l< 10; l++)
And
printf("%f\n", data[10][7]);
To
printf("%f\n", data[l][k]);
And move the printf just after
data[l][k] = num;
The former is done because array indices start from 0 and end at length-1.
The latter is done because you need to loop through the array to get each value that is stored in each index of the array and print it. You can't just use data[10][7] and expect the whole array to be printed. data[10][7] is an invalid location and accessing it invokes Undefined Behavior which means that anything can happen including segmentation faults, runtime errors, crashes etc.
Also, add a return -1; in the end of the body of the first if to end the execution of the program if the fopen failed to open its first argument.

Resources