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.
Related
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
I am trying to create an array from the integers that a user inputs. They must be inputted on the same line, e.g. 5 1 2 3 1 6. The number of integers can be any amount.
However, the first number + 1 determines the size of the array. E.g. if the user inputs the number 5 first, it must be followed by 5 other random integers thus making the length of the array 6. I'm getting confused on how to do this because there is so much user input. Thanks in advance!
Here is my code so far, though i don't think it'll be much help:
#include <stdio.h>
int main(void) {
int arr_days[13];
int i = 0;
printf(" ");
while(i < 13) {
scanf("%d", &arr_days[i]);
i = i + 1;
}
printf("%d", arr_days[0]);
return 0;
}
You weren't too far off, you just need to allocate the buffer dynamically and read the first number separately so that you know how much space and how many loops to perform.
You might also want to check if arr_days is NULL after the malloc to protect against 'out of memory' problems.
#include <stdio.h>
int main(void) {
int* arr_days;
int i = 0;
int n;
printf(" ");
// get first number to find out how many more to expect
scanf("%d", &n);
// create memory space to store them
arr_days = malloc(n * sizeof(int));
while(i < n) {
scanf("%d", &arr_days[i]);
i = i + 1;
}
printf("%d", arr_days[0]);
return 0;
}
EDIT: I see from some comments further down that there is some confusion about scanf. This command will trigger an input request if there is no input pending, then it will process any pending input. So when you type in a bunch of numbers in response to a scanf input prompt (or pipe a text file with those numbers in to the program) each invocation of scanf("%d",...) will only extract the next single integer, leaving the rest of the input still available. If you think of it like the string is a file, scanf is reading from that file and leaving the file pointer at the end of the bit it just read ready for the next invocation to read the next bit... (which is exactly what happens if you pipe a text file!)
First you would need to get the number so that you know how many numbers to read and how big to allocate the array.
int num;
scanf("%d", &num);
int *arr = malloc(num * sizeof(int));
Second, read each of the numbers one by one.
int I;
for (I = 0; I < num; I++) {
scanf("%d", &arr[I]);
}
This shows as an example of how to do the task, you will need to take care of check scanf's result to make sure the input was successful, and check malloc for allocation too.
If you want to set the array size based on an input then the input has to be read first. What you want is to input all numbers in a line(including size of the array), which means the numbers will be read after the end of line only(after pressing [Enter]). This case is not possible with static arrays.
You can't read all the inputs i.e. array size & integers to be put in it on the same line & build an static array. But you may build a dynamic array by implementing a dynamic array and taking all inputs in the same line.
A dynamic array is a re-sizable array or array list with random
access, variable-size list data structure that allows elements to be
added or removed.
A static array required the size of the array to be created so
that that memory could be allocated before array elements can be added
to it.
All this being said,
if your array size has an upper-bound size(i.e. the maximum number of elements which you would accept is set) then you may create a static array of the maximum size and read you inputs into it.
int arr[MAX_ARRAY_SIZE ASSUMED];
This allocates an array of size MAX_SIZE_ASSUMED which means all your inputs maybe stored in the static array. But this is a bad way to implement as MAX_SIZE_ASSUMED is always the size of the array even when you may just enter one element into the array.
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
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.
}
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