I just figured out how to do this with integers so decided to give it a go with strings and got stuck.
Here is what is in my file "kw":
keyword0
keyword1
keyword2
keyword3
With this current code I'm getting "error: format '%s' expects argument of type 'char *', but argument 3 has type 'char **'
#include <stdio.h>
int main () {
FILE *pFile;
pFile = fopen("kw", "r");
if (pFile != NULL) {
char *a[3];
int i;
for(i = 0; i <= 3; i++) {
fscanf(pFile, "%s", &a[i]);
printf("%s\n", a[i]);
}
}
return 0;
}
Could someone point me in the right direction here? Thank you.
There are several problems with this code:
You are going through four elements of the array a, while the array has only three elements.
You did not allocate space for the strings that you are reading with scanf.
You do not pass the address of address when you read strings.
To fix the first problem, change <= for != or <, like this:
for(i = 0; i != 3; i++)
To fix the second and the third problem, use malloc:
a[i] = malloc(21*sizeof(char));
fscanf(pFile, "%20s", a[i]);
Once you are done with the data that you allocated, don't forget to free the strings:
for(i = 0; i != 3; i++) {
free(a[i]);
}
Related
I started learning C recently. I'm having some difficulty with strings, especially in the matter of storing list of names, phrases, words and displaying them later. Here's my code:
#include <stdio.h>
int main()
{
char names[3][10];
printf("Type 3 names: \n");
for (int i = 0; i<3; i++)
{
scanf("%10s", names);
}
printf("\n\nName list:\n\n");
for (int j = 0; j<3; j++)
{
for (int k = 0; k<10; k++)
{
printf("%s", names[k][j]);
}
}
return 0;
}
My intention is to store full names and with spaces and display them listed later.
When I run the code, the program does not ask for 3 names and does not display correctly the ones that have been typed.
Any tips on how I can fix it?
Please turn up the warning level of your compiler. It should have warned you about at least two things:
(20): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'int'
(20): warning C4313: 'printf': '%s' in format string conflicts with argument 1 of type 'int'
In your first for-loop you do count to 3 but you miss specifying that you want to read from stdin to names[i]. Change
scanf("%10s", names);
to
scanf("%10s", names[i]);
In your second loop the nested for-loop is not neccessary since printf() will take care of printing each char in names[j] until it encounters a '\0' which terminates the string. So change
for (int j = 0; j<3; j++)
{
for (int k = 0; k<10; k++)
{
printf("%s", names[k][j]); // doesn't match. names[i][j] is a char *)
}
}
*) which propagates to an int due to parameter passing to a function with a variable length parameter list while the format string "%s" causes printf() to expect a pointer to char.
to
for (int j = 0; j < 3; j++)
{
printf("%s\n", names[j]);
}
Please also mind that since you want to read names up to 10 characters in length your array needs to be
char names[3][11]; // not [3][10]
to accomodate for the terminating '\0' character.
How can I input 2 strings which are separated by a new line?
My Problem:
First I need to give how many strings I need to get and then I need to get those strings then display it.
I tried this:
Code:
#include <stdio.h>
#include <string.h>
int main()
{
int n,i = 0;
scanf("%d", &n);
char arr[n][100];
for(int i = 0; i < n; i++)
{
scanf("%[^\n]s", arr[i]);
}
for(int i = 0; i < n; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}
My Input is :
2 I am
Aravind
My Output is:
I am
þ
First Line I got correct one but second line it shows some garbage value. Help me to solve this.
You have two major problems:
The "%[" format ends with the closing "]", there should be no "s" at the end.
The "%[" format doesn't skip leading space, like that newline which will be present after the first line you read.
Both these issues can be easily solve by using fgets to read whole lines instead.
You already have suggestions to not use scanf. However, if you 'must' use scanf then you can consider the following approach:
For dynamic memory allocation you should use malloc
the newline character stays in the stdin and hence needs to be flushed or handled/ignored
Here is the updated code.
int main()
{
int n,i = 0;
scanf("%d", &n);
scanf("%*[\n]");
/*this will read the \n in stdin and not store it anywhere. So the next call to
* scanf will not be interfered with */
char **inputs;
inputs = malloc(n * sizeof(char *));
for (i = 0; i < n; i++)
{
inputs[i] = malloc(100 * sizeof(char));
}
for(i = 0; i < n; i++)
{
scanf("%*[\n]");
scanf("%100[^\n]", inputs[i]);
}
for(i = 0; i < n; i++)
{
printf("%s\n", inputs[i]);
}
return 0;
}
use gets(arr[i]) instead of scanf.
I am making a program to check for funny strings. To understand the exercise read this.
My code is here:
#define MAX_STR_LENGTH 10
char* reverse(char *str) {
char *reversedStr = malloc(strlen(str));
for (int i = 0; i < MAX_STR_LENGTH; i++) {
for (int j = MAX_STR_LENGTH - 1; j > 0; j--) {
reversedStr[i] = str[j];
}
}
return reversedStr;
}
int isFunny(char *str, char *reversedStr) {
for (int i = 1; i < MAX_STR_LENGTH; i++) {
if (str[i] - str[i - 1] != reversedStr[i] - reversedStr[i - 1]) {
return 0;
}
}
return 1;
}
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int numberOfStrings;
scanf("%i", &numberOfStrings);
char **strings;
for (int i = 0; i < numberOfStrings; i++) {
scanf("%s", &strings[i]);
}
char **reversedStrings;
for (int i = 0; i < numberOfStrings; i++) {
reversedStrings[i] = reverse(strings[i]);
}
for (int i = 0; i < numberOfStrings; i++) {
if (isFunny(strings[i], reversedStrings[i])) {
printf("Funny\n");
}
printf("Not funny\n");
}
return 0;
}
The error I am getting is the following:
solution.c: In function 'main':
solution.c:35:9: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char **' [-Wformat=]
scanf("%s", &strings[i]);
I don't understand why though.
My aim was to make an array of strings, called strings, and store there all the strings that I read. Why is strings[i] a char** ?
I would appreciate any help or tips.
Thanks!
Apparently you have a char * and you are passing it's address, which is wrong, scanf() wants a char pointer for each "%s" specifier, and the fix for your code is to use
char string[10];
scanf("%s", string);
the array automatically becomes a char pointer when passed to scanf() like above, but that's not enough.
Your array of char now as I suggest it is of fixed size, and even if it wasn't, using scanf() like that is dangerous, suppose that each array in the array of char arrays has 10 elements, then each string you want to read must have only 9 characters, you can instruct scanf() to stop reading when it already read 9 characters like this
scanf("%9s", strings[i]);
If you don't do this, then reading extra characters will be possible, but illegal, causing what's called undefined behavior.
If you want an array of strings, say of 5 strings with 9 characters each, then you can try
char strings[5][10];
int i;
for (i = 0 ; i < 5 ; ++i)
scanf("%9s", strings[i]);
Note: You need the & address of operator for example, when you pass an int value, because scanf() modifes the data pointed to by the passed pointer, so you need to make a pointer to the int variable where you want to scan the value, for that you use the & address of operator, since you pass a pointer containing the address of the variable.
Suggestion: Always check the return value of malloc(), it returns NULL on failure, and dereferencing a NULL poitner, is undefined behavior, you must be careful not to cause undefined behavior because it's too hard to debug.
I have a file with a large quantity of number and I need to read every single line, and then put every number in that line in an array.
This is two line of my file:
7.7560198e+002 8.2334910e+002 9.7819197e+002 1.4330775e+003 3.0535763e+003 3.3218925e+003 1.7164341e+003 3.1848433e+003 4.9317846e+002 3.4466984e+002 4.7654154e+002 4.9282917e+002 9.5322001e+001 1.2369945e+002 5.3310001e+001 1.0394150e+002 3.1919280e+003 2.1591746e+003 2.1608040e+003 3.6585112e+003
7.1244665e+002 1.4142187e+003 1.7148456e+003 1.3126353e+003 3.4328919e+003 2.8380069e+003 2.8432808e+003 3.6142229e+003 3.3866501e+002 3.9236491e+002 5.0149915e+002 5.9447907e+002 1.3568213e+002 5.9164038e+001 7.1649000e+001 1.3451865e+002 2.2922576e+003 1.8212714e+003 2.9237970e+003 5.1605066e+003
I tried with this code:
FILE *f = fopen(pathInput,"r");
if(f==NULL) {
printf("Error\n");
return -1;
}
int i, j, columnsNumber=0, rowsNumber=0;
char c;
c = fgetc(f);
// count number of column with the first line
for(i=0;c != '\n'; i++) {
if (c==' ') {
while(c==' ')
c = fgetc(f);
numCol++;
}
c = fgetc(f);
}
// count the rows
while(!feof(f)){
c = fgetc(f);
if(c == '\n'){
rowsNumber++;
}
}
float input[(rowsNumber)* columnsNumber];
for(j=0; j< rowsNumber;j++){
for (i = 0; i < columnsNumber; i++){
fscanf(f, "%f ", input[i] );
}
}
for(i=0;i<10; i++){
printf("%f\n", input[i]);
}
fclose(f);
But it doesn't work and the I obtain this warning:
warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘float *’ [-Wformat=]
printf("%f\n", input[i]);
In your code, you create an array of pointers to floats. You're actually looking to create an array of floats. That declaration would look like the following. Note the lack of a float *.
float input[rowsNumber * columnsNumber];
At that point, you'll get a warning from fscanf(). You're supposed to pass a pointer to an allocated piece of memory. So:
fscanf(f, "%f ", &input[j*columnsNumber + i]);
And, you'll also have problems because you are attempting to read the file twice. You'll want to either close and reopen the file, or reset the file to be looking at the beginning of the file with fseek().
Finally, and I'm not 100% sure on this, but I think it's likely that between when you count the number of floats in a column and the number of floats in a row, you'll possibly miss one '\n' character.
I am working on a project in C which requires me to read in matrix values from a txt file. The first two lines are the number of rows and columns, and the rest is the actual matrix data.
For example, something like this:
2
2
1.0 2.0
3.0 4.0
The code I wrote is giving me some issues. Here's a snippet:
matrix read(char* file){
FILE *fp;
printf("check 1\n");
fp = fopen(file,"r");
printf("file opened\n");
// Make the new matrix
matrix result;
printf("matrix created\n");
int counter = 0;
int i;
int j;
int holdRows;
int holdColumns;
if(counter == 0)
{ // read in rows
fscanf(fp, "%li", holdRows);
printf("here is holdRows: %li\n", holdRows);
counter++;
}
if(counter == 1)
{ // read in columns
fscanf(fp, "%li", holdColumns);
printf("here is holdColumns: %li\n", holdColumns);
counter++;
// Now that I know the dimensions, make the matrix
result = newMatrix(holdRows, holdColumns);
}
// For the rest, read in the values
for(i = 0; i < holdRows; i++)
for(j = 0; j < holdColumns; j++)
fscanf(fp, "%lf", &result->matrixData[i][j]);
fclose(fp);
return result;
}
Whenever I run this, holdRows and holdColumns are not the values stored in the txt file. For example, I tried a 3X4 matrix, and it read that there was one row and three columns.
Can anyone tell me what I'm doing wrong?
Thanks :)
Thanks to suggestions by you all and some sleuth work myself, I solved my problem. First, I was entering the wrong filename (well, now I feel silly), and second, I was reading the data in as the wrong type.
Thanks, everyone, for your help!
You are not passing the address of holdRows and holdColumns to fscanf. You have to change them to fscanf(fp, "%li", &holdRows); and fscanf(fp, "%li", &holdColumns);.
the %li conversion specification requires a long* as matching argument to fscanf(): you're passing a int (int* after correction proposed by dbarbosa).
Try "%i" ... and same for printf().
The %lf expects a double. Is matrix made of doubles?
Try replacing:
for(i = 0; i < holdRows; i++)
for(j = 0; j < holdColumns; j++)
fscanf(fp, "%lf", &result->matrixData[i][j]);
with
double temp;
for(i = 0; i < holdRows; i++)
for(j = 0; j < holdColumns; j++) {
fscanf(fp, "%lf", &temp);
result->matrixData[i][j] = temp;
}
I seem to recall that in C some types of 2D arrays don't play nice with &.