Ascending order arrangement of numbers of a file - c

How to read a file which contains two columns and sort the first column numbers in ascending order and to print them with their corresponnding 2nd column values using C ?

fopen opens a file.
fscanf reads from a file and splits what is read into bits according to a format specification (e.g. "%d %s" means an integer followed by whitespace followed by a string of non-whitespace characters).
qsort is a standard library function that will sort an array. It sorts the array by comparing one item to another item. You give it the name of a function (which you write) that does this comparison.
I encourage you to read the manual pages for these functions if you are not familiar with them.
The program below uses all this to:
Open a file test.txt
Read lines from the file into an array arr
Sort the array using qsort, using the rowcmp function (rowcmp looks at the numerical value in the first column to determine whether one element is greater than, equal to, or less than another element)
Print out the elements of the array.
The code...
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 100
#define MAXITEMS 100
// A row has two columns, the first is a number and
// the second is any string of up to MAXLEN chars
struct row {
int col1;
char col2[MAXLEN];
};
// Function to do comparison of rows
// Sorts numerically on the value in the first column
int rowcmp(struct row * r1, struct row * r2) {
if (r1->col1 < r2->col1) return -1;
if (r1->col1 == r2->col1) return 0;
return 1;
}
int main(int argc, char ** argv) {
struct row arr[MAXITEMS]; // up to MAXITEMS rows
int rows = 0, i;
FILE * stream = fopen("test.txt", "r");
// Read in rows and put first and second columns into struct,
// building up an array
while (fscanf(stream, "%d %s", &(arr[rows].col1), arr[rows].col2) !=EOF) {
rows++;
}
// Sort the array using the rowcmp function to compare items
qsort(&arr[0], rows, sizeof(struct row), (__compar_fn_t)rowcmp);
fclose(stream);
// Print the sorted array
for (i=0; i<rows; i++) {
printf("%d\t%s\n", arr[i].col1, arr[i].col2);
}
}
With input file:
1 apple
3 cucumbers
21 dates
7 figs
4 grapes
output is
1 apple
3 cucumbers
4 grapes
7 figs
21 dates

Related

importing an ascii grid file in C

Sorry, but I know how to do it in other languages, but C is rather new to me.
I need to import an ascii grid file in a C code. The structure of the file is as follows:
ncols 12
nrows 101
xllcorner 2.0830078125
yllcorner 39.35908297583665
cellsize 0.00439453125
nodata_value -2147483648
401.99 407.38 394.17 362.35 342.36 335.13 319.91 284.99 262.88 259.58 245.62 233.58
397.63 396.36 380.70 358.96 339.35 327.96 314.06 296.73 279.11 264.80 257.20 249.97
389.71 381.29 356.41 338.75 326.04 323.36 317.67 301.30 281.79 269.46 261.94 250.72
.....
I can read the bulk of values but I am struggling to properly import the first 6 lines in two arrays, a character one (namevar) and a double one (valvar).
My only partially working code is:
#define ny 101
#define nx 12
#define dime nx *ny
int main(void)
{
FILE *dem;
double Z[dime], varval[6];
char namevar[12];
int l = 1;
dem = fopen("buttami.txt", "r");
int i;
int j;
while (l < 7)
{
//
fscanf(dem, "%s %f\n", &namevar, &varval[l]);
printf("%s %.8f\n", namevar, varval[l]);
l++;
}
for (i = 1; i < dime; i++)
{
fscanf(dem, "%lf", &Z[i]);
printf("%.5f ", Z[i]);
printf("\n");
}
fclose(dem);
}
Comments address many issue, this focuses on your specific mention...
"I am struggling to properly import the first 6 lines in two arrays, a character one (namevar) and a double one (valvar)"
First, the variable char namevar[12]; is too small to contain the longest name string it will need to contain: "nodata_value" as stored in the file contains 12 characters requiring the variable namevar to be created with size of at least 13 to provide room for the null terminator. ( see definition of C string )
The top part of the input file could be thought of as a header section, and its content as tag/values. An array of struct is useful to store content of varying types into a single array, each containing a set of members to accommodate the various types, in this case one C string, and one double. For example:
#define NUM_HDR_FLDS 6 // to eliminate magic number '6' in code below
typedef struct {
char namevar[20];
double varval;
} header_s;
header_s header[NUM_HDR_FLDS] = {0};//array of NUM_HDR_FLDS elements, each contains two members,
//1 a char array with room for null terminator for field name
//2 a double to contain value
Then your fscanf() loop will look like this:
//note changes to format specifier and the
//string member needs no &
int l=0;//C uses zero base indexing
dem=fopen("buttami.txt", "r");
if(dem)//test for success before using
{
while(l<NUM_HDR_FLDS){//zero base indexing again (0-5)
if(fscanf(dem,"%s %lf", header[l].namevar,&header[l].varval) == 2)
{
printf("%s %.8f\n",header[l].namevar,header[l].varval);
} //else handle error
l++;
}
fclose(dem);
}
By your example data description, I guess it is Arc/Info Ascii Grid foramt by wikipedia https://en.wikipedia.org/wiki/Esri_grid.
For raster data files I/O, please try library Gdal.
Gdal doc about this format https://gdal.org/drivers/raster/aaigrid.html
Here is code samples for open and read a raster file https://gdal.org/tutorials/raster_api_tut.html

C - Incorrect result in counting number of empty elements in a 2D array

I am creating a program for a college assignment where the user is required to input artists and their songs. The program then sorts them alphabetically and shuffles them. Artist names are stored in an array called artists[][80] and song names are stored in songsArtistx, where x is a number from 1 to 4. I initialised all arrays to be filled with the NULL terminator - '\0'. For the program to work, I need to find the number of songs entered (have to be at least 1, but can be 3 or less). To achieve this, I am using a function called checkSongs:
int checkSongs(char songsOfAnArtist[][80])
{
int i,numOfSongs;
//Loop goes through 4 possible artists.
for (i=0;i<4;i++)
{
//Assume there are 3 songs for each artits, and decrement by 1 each time an empty string occurs.
numOfSongs = 3;
if (songsOfAnArtist[i][0]=='\0' || songsOfAnArtist [i][0] == '\n')
{
numOfSongs--;
break;
}
}
return numOfSongs;
}
However, this function gives me a faulty result for when the number of songs is less than 3. Here is an example from the command line, and also a screenshot of the variables from the debugger:
In the photo above, the numbers on the last line indicates the number of artists inputted (which is correct in this case) and the number of songs in songsArtsist1, songsArtsist2, songsArtsist3, songsArtsist4 respectively. The last number is the number of artists again.
How do I alter my code so that checkSongs returns the number of songs entered for each artists?
Below is also an excerpt from the main file which could be relevant to the question:
//Get all inputs from command line: artists and songs
getInputs(artists,songsArtist1,songsArtist2,songsArtist3,songsArtist4);
//Use checkArtists to store the number of entered artists in variable 'numOfArtists'
numOfArtists = checkArtists(artists);
printf("%d ",numOfArtists);
//Use check songs to store number of songs per artist in array 'numSongsPerArtists'
numSongsPerArtist[0] = checkSongs(songsArtist1);
numSongsPerArtist[1] = checkSongs(songsArtist2);
numSongsPerArtist[2] = checkSongs(songsArtist3);
numSongsPerArtist[3] = checkSongs(songsArtist4);
//DEBUG
printf("%d ",numSongsPerArtist[0]);
printf("%d ",numSongsPerArtist[1]);
printf("%d ",numSongsPerArtist[2]);
printf("%d ",numSongsPerArtist[3]);
printf("%d ",numOfArtists);
Here are there arrays:
//The array containing artists names
char artists[4][80];
//The array containing the sorted artists
char sortedArtists[4][80];
//Songs for Artist 1
char songsArtist1[3][80];
//Songs for Artist 2
char songsArtist2[3][80];
//Songs for Artist 3
char songsArtist3[3][80];
//Songs for Artist 4
char songsArtist4[3][80];
//The total number of artists (Note it can be less than 4)
int numOfArtists = 0;
//The total number of songs for each artist (Note that less than 3 songs can be provided for each artist)
int numSongsPerArtist[4] = {0,0,0,0};
When you write a function that takes an array as argument, it always should ask
for the length from the caller, unless the end of the array is marked somehow
(like '\0' for strings). If you later change you program to accepts more or
less number of songs and you forget to update the loop conditions, you are in a
world of trouble. The caller knows the size of the array, either because it
created the array or because the array along with it's size was passed. This is
standard behaviour of the functions in the standard C library.
So I'd rewrite your functions as:
int checkSongs(char songsOfAnArtist[][80], size_t len)
{
int numOfSongs = 0;
for(size_t i = 0; i < len; ++i)
{
if(songsOfAnArtist[i][0] != 0 && songsOfAnArtist[i][0] != '\n')
numOfSongs++;
}
return numOfSongs;
}
And then calling the function
numSongsPerArtist[0] = checkSongs(songsArtist1, sizeof songsArtist1 / sizeof *songsArtist1);
numSongsPerArtist[1] = checkSongs(songsArtist2, sizeof songsArtist2 / sizeof *songsArtist2);
numSongsPerArtist[2] = checkSongs(songsArtist3, sizeof songsArtist3 / sizeof *songsArtist3);
numSongsPerArtist[3] = checkSongs(songsArtist4, sizeof songsArtist4 / sizeof *songsArtist4);
This is better because if you later change from char songsArtist3[3][80]; to
char songsArtist3[5][80];, you don't have to rewrite the boundaries in the
loop conditions. Every artists can have a different size of slots for the songs.
And when you store the song names, make sure that the source string is not
longer than 79 characters long, use for example strncpy and make sure to write the '\0'-terminating byte.
If you keep having the wrong results, then it may be that the songsArtists
variables are not initialized correctly, please check your getInputs function
so that all songsArtist[i][0] are set to 0 on initialization. If you do
that, you should get the correct results.
For example:
int main(void)
{
...
char songsArtist1[3][80];
char songsArtist2[3][80];
char songsArtist3[3][80];
char songsArtist4[3][80];
memset(songsArtist1, 0, sizeof songsArtist1);
memset(songsArtist2, 0, sizeof songsArtist2);
memset(songsArtist3, 0, sizeof songsArtist3);
memset(songsArtist4, 0, sizeof songsArtist4);
...
}
Add a condition in the block where you break the loop.
if(sumOfSongs==0)
break;
Also I would recommend to use unsigned types for the variables as the numbers most likely can never be less than 0;
And put numOfSongs = 3; outside the for loop as others suggested.

C reading input from a file into 2d array - variable number of lines per row

I am reading a list of grades from a txt file into an array. It worked fine when reading user input, but I'm having trouble reading each line when scanning from file. The number of students is variable. The number of grades per student is variable. I have no trouble reading the number of students and number of assignments, but when reading from file I'm having trouble pulling the int (grade) from each line for each student. The input may be like a or b (or any larger number of students/assignments):
txt-example1 (the comments including and after // are my own and not in txt file)
2 //number of students
3 //the number of grades per student (will match the number of grade rows below)
theo alvin //the number of names will match the number of students
75 60
89 90
79 95
txt-example2
3
4
theo alvin simon
78 85 90
85 96 76
77 99 100
88 55 92
I can put the names into 1 dimension of a 2d array (I'll use the second dimension later to print - no problems with that part). I want to get the grades into a 2d array. Here is what I have
#include<stdio.h>
#include<string.h>
int numStus;
int numGrades;
int main()
{
FILE* inputFile;
char stuNames[numStus][10];
int grades[numGrades][numStus];
inputFile = fopen("testData.txt","r"); //assume inputFile has data from Ex 1 or 2 above
fscanf(inputFile,"%d",&numStus);
fscanf(inputFile,"%d",&numGrades);
int i;
int j;
for (i=0; i<numStus; i++)
{
fscanf(inputFile,"%s",&stuNames[i]);
}
//here is where I'm having trouble
for(i=0;i<numGrades;i++)
{
for(j=0;j<numStus; j++)
{
//I want to use fscanf, but don't know how to account for carriage returns to iterate into next part of array
}
}
}
What worked when getting from user input:
int i;
int j;
int k;
for (i=0; i<numGrades; i++)
{
for (j=0; j<numStus; j++)
{
printf("Enter grade for Assignemnt %d for ",i)
for(k=0;k<10;k++)
{
printf("%c",stuNames[j][k]);
}
scanf("%d",&grades[i][j]);
}
}
The part immediately above worked well for user input grades. When getting the same input from a file I'm not sure how to get the grades into the proper dimensions. Any advice on how to account for the newline/CR to increment the array would be very much appreciated. Thanks.
The scanf can be used in the nested loops as usually for reading a single value, since the carrige return is skipped as a space, for example: fscanf(inputFile,"%d",&grades[i][j]);
However, the arrays stuNames and grades must be initialized only after reading numStus and numGrades, for example:
...
fscanf(inputFile,"%d",&numStus);
char stuNames[numStus][10];
fscanf(inputFile,"%d",&numGrades);
int grades[numGrades][numStus];
...
That trick is not allowed in ANSI C. In that case dynamic memory allocation should be used.
You have trouble much earlier than you think. You can't use uninitialized variables when you are declaring your arrays. In your working example you don't show how you allocated your arrays. Were they fixed size? Whatever you did there would probably work in your new program.
You first need to read the amount of students and amount of grades.
A uninitialized variable like int foo; has a "random" value.
You need to initialize the variable like int foo = 0;.
Knowing this lets analyze your code step by step.
int numStus; //numStus gets random value
int numGrades; //numGrades gets random value
int main()
{
FILE* inputFile;
char stuNames[numStus][10]; //random amount gets generated
int grades[numGrades][numStus]; //variable gets random value
fscanf(inputFile,"%d",&numStus); //numStus gets actual value
fscanf(inputFile,"%d",&numGrades); //numGrades gets actual value
C is a language which handles things in order.
This means that the array keeps the size is has been given.
The code can be fixed by switching around the statements like this:
int numStus; //numStus gets random value
int numGrades; //numGrades gets random value
int main()
{
FILE* inputFile;
fscanf(inputFile,"%d",&numStus); //numStus gets actual value
fscanf(inputFile,"%d",&numGrades); //numGrades gets actual value
char stuNames[numStus][10]; //array of wanted size gets created
int grades[numGrades][numStus]; //random amount gets
I hope this helps, may you have any questions ask them

How to store this kind of data in an array

The input consists of multiple lines.
The first line contains a number n which indicates that the number of rows in the Pascal’s triangle will be n+1.
The second line contains a number m which indicates the number of transactions to be performed on the Pascal’s triangle. Each transaction is given in a separate line. A transaction is a space separated list of integers. The first integer in each list indicates the row number, say R, and the rest of the integers in the list indicate the indices of values in row R. For each transaction, you have to compute the sum of given coefficients in the given row R.
Example: Input will be given in the following format:
5
3
3 1 2
5 1 1 1 4
4 2 3 2
what should be done to store the values of transition lines like
3 1 2
5 1 1 1 4
4 2 3 2
under a single array variable.So that it can be passed to a function completely.
If you make a structure like this you might be able to do what you are trying to do. You can pass structure to function to compute sum of each line.
struct pascaltirangle
{
int size; //The no of lines
int* no_transactions; //To store no of transactions of each line
int** contents; //To store contents of each line. No of contents in line determined by transaction[i]
} dat;
//code to take input of size
dat.no_transactions=(int*)malloc(sizeof(int) * (dat.size+1));
//code to take no of transaction for each line
for(int i=0;i<=dat.size;i++)
contents[i]=malloc(sizeof(int)*dat.no_transaction[i]);
//code to take input for contents[i][j]
It simply adds all the transactions for a line using recursive function.
#include <stdlib.h>
#include <stdio.h>
int add_transaction(int *contents,int size)
{
if(!size)
return 0;
return (*contents + add_transaction(contents+1,size-1));
}
void main()
{
int size; //The no of lines
int* no_transaction; //To store no of transactions of each line
int** contents; //To store contents of each line. No of contents in line determined by transaction[i]
int c1,c2;
printf("Give size of triangle :");
scanf("%d",&size);
no_transaction=(int*)malloc(sizeof(int) * (size+1));
contents=(int**)malloc(sizeof(int)*(size+1));
for(c1=0;c1<=size;c1++)
{
printf("\nGive no of transaction for line no %d :",c1+1);
scanf("%d",no_transaction+c1);
contents[c1]=(int*)malloc(sizeof(int)*no_transaction[c1]);
for(c2=0;c2<no_transaction[c1];c2++)
{
printf("\tFor line %d give transaction no %d :",c1+1,c2+1);
scanf("%d",contents[c1]+c2);
}
}
printf("\nThe sum of the series is :");
for(c1=0;c1<=size;c1++)
{
if(c1)
printf("+ %d ",add_transaction(contents[c1],no_transaction[c1]));
else
printf(" %d",add_transaction(contents[c1],no_transaction[c1]));
}
//Code to free the allocated memory.
}

Taking Input from a file Travelling Salesman in C

I am working on TSP which takes large number of city like 100 ,500 etc. I have wrote a code using greedy algorithm and works fine using command line arguments . But I need to take input from a file which has the below given format.
First line is the number of cities
Second line is 'euclidean' or'not euclidean'
Now from 3rd line we have co-ordinate of n cities (float)
And after cordinates we have nxn distance matrix for each city.
Something like that lets take number of city be 5
5
euclidean
1.3 4.2
1.6 -3.5
1.4 1.5
6.4 3.6
4 2.4
now a 5x5 cost matrix.
How do i store all the input in array ? (n,euclidean/non-euclidean,cordinates,matrix) After taking the input i need to work on the matrix itself.
I wouldn't store it all in one single array. First of all, worry about reading the number of cities. After you know that, you can allocate 2 arrays: one of them holds a structure with the coordinates for each city, and the other is a 2D array where you store the costs.
This assumes that you look at the cities and count them: in your example, the city with coordinates 1.3 4.2 will be city 0 (stored in position 0 of the array); the city with 1.6 -3.5 will be on position 1, etc. So, basically you'll be doing:
Read number of cities, x;
Read whether it's euclidean or not, store that in some variable;
Allocate an array cities of x elements, and another
bi-dimensional array costs of x by x;
Read each city's coordinates, and store them in cities[i] (cities
shall be an array of a structure with 2 floats to store the
coordinates);
For each line i (i starting on 0) and for each column j in that line
(also starting on 0), set cost[i][j] to whatever value is in the
input.
Here's the code that implements this approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 32
struct city {
float c1;
float c2;
};
int main(void) {
int citiesNo, i, j;
struct city *cities;
float **cost;
char line[BUFSIZE], euclidean[BUFSIZE];
fgets(line, BUFSIZE, stdin);
citiesNo = atoi(line);
fgets(line, BUFSIZE, stdin);
strcpy(euclidean, line);
cities = malloc(sizeof(struct city)*citiesNo);
cost = malloc(sizeof(float *)*citiesNo);
for (i = 0; i < citiesNo; i++)
cost[i] = malloc(sizeof(float)*citiesNo);
/* Read coordinates */
for (i = 0; i < citiesNo; i++)
scanf("%f %f", &(cities[i].c1), &(cities[i].c2));
/* Read costs */
for (i = 0; i < citiesNo; i++)
for (j = 0; j < citiesNo; j++)
scanf("%f", &(cost[i][j]));
/* Everything is stored now... */
return 0;
}
fgets was used in the beginning because scanf("%d", &citiesNo) would leave a newline in the buffer, and the subsequent fgets() call would return an empty line. If you prefer, you can replace both fgets() by scanf(), I just didn't read the euclidean string with scanf because it makes no buffer size checking. If your input is always well formed, this is not a problem.
After this code runs, you have a string with "euclidean" or "not euclidean" stored in the variable euclidean.

Resources