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
Related
I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)
This question already has answers here:
Pointer to string changes its value unexpectedly
(4 answers)
Closed 4 years ago.
I would like to create an array in C and then assign to every value in that array the string "[ ]".
This is what I have in mind:
char Array[N];
for(int i = 0; i < N; i++)
{
Array[i]="[ ]";
}
What is the correct approach to doing that?
Bellow is a sample working code you customize to your taste:
#include<stdio.h>
#include<string.h> // for strcpy: use to copy one string into another
// set a symbolic constant
#define N 10
int main(int argc, char **argv)
{
// declare the array
char Array[N][4]; // 4, because "[ ]" is 3+1 long
for(int i=0; i < N; i++){
strcpy(Array[i], "[ ]");
}
// print out the content for test purpose
for(int i=0; i < N; i++){
printf("Array[%d] = %s\n", i, Array[i]);
}
return 0;
}
This question already has an accepted solution but I'd like to provide a bit more context that will help people who are used to higher-level languages like Java and C++ understand why these steps are needed when writing this algorithm in C vs. in a newer language.
For starters, not every C compiler will allow you to create an array with a size determined by a variable (this is called a Variable Length Array, or VLA--you can read more about them here: How do I declare a variable sized array in C?). Unfortunately you can't even declare a const variable for the number of terms you want in your array (read more about that here: Can a const variable be used to declare the size of an array in C?). So that's why you're stuck typing the literals everywhere in the program or using preprocessor commands like I've demonstrated.
Next, the length of a char array in C is the number of chars it can hold. However, since each of your terms is 3 characters long plus the null character at the end you need the array to be 4 times longer than the number of terms. You can use two See the code below for how to declare this.
Finally, you need to #include the string.h header file in order to be able to work with strings in C.
#include <stdio.h>
#include <string.h>
int main(){
#define N_TERMS 6
#define L_TERM 4
char term[L_TERM] = "[ ]";
char Array[N_TERMS * L_TERM] = ""; //array should be the size of the product of number of terms and length of term
for(int i = 0; i < N_TERMS; i++){
strcat(Array, term); //strcat adds the second string to the end of the first
}
printf("%s", Array); //prints the entire string
return 0;
}
A char is one character. Which would be in single quotes not double quotes. "[ ]" is three character. [, the space and ] are together three characters. Each index in a char array can only hold one character at a time, so the [ or the space or the ] or some other character.
The text file contains 52 lines that are in the format:
A .013420
B .000191
C .011222
...
I want to ignore the letters and I need to extract the values from the file and store the first 26 in one array which I named freqOne[] and store the last 26 values in another array named freqTwo[]. I will later use these values for calculations.
here is my attempt:
#include <stdio.h>
#include <stdlib.h>
int main (){
FILE *input1;
/*char freqOne[26]; i use these arrays for attempt 1
char freqTwo[26];*/
double freqOne[26];
double freqTwo[26];
input1 = fopen("test8.txt", "r");
if(input1 == NULL){
perror("test8.txt");
exit(EXIT_FAILURE);
}
/* attempt one: all the values print out correctly but idk how to use them :(*/
/*while(fgets(freqOne, sizeof(freqOne), input1)){
printf("%s", freqOne);
}
while(fgets(freqTwo, sizeof(freqTwo), input1)){
printf("%s", freqTwo);
}
*/
/*fclose(input1); */
int h;
int i;
/* another attempt i made, this one prints out the a large negative number for every element :(*/
for(i=0; i<26; i++){
fscanf(input1,"%lf", &freqOne[i]);
printf("%lf\n", freqOne[i]);
}
for(h=0;h<26; h++){
fscanf(input1,"%lf", &freqTwo[h]);
printf("%lf\n", freqTwo[h]);
}
fclose(input1);
/*a = (freqOne[0]-freqTwo[0])*(freqOne[0]-freqTwo[0]);
printf("%lf", a);*/
}
In my first attempt, i was able to print out all the values correctly, but I am not sure how to use them. I printed them out as strings, but when I try to print them out as %lf, it gave me 0's for every value.
In my second attempt, I did some googling and found that I should try the fscanf function, but this did not work for either and a large negative number was printed out for every value. I am pretty stuck right now and out of ideas.
So OP can close this post:
To ignore the A,B,C, etc., use assignment suppression '*'
// fscanf(input1,"%lf", &freqOne[i]);
fscanf(input1,"%*s %lf", &freqOne[i]);
Always a good idea to check I/O function results:
if (fscanf(input1,"%*s %lf", &freqOne[i]) != 1) Handle_Unexpected_Input();
I've been pouring over my code (which does not work) now for quite some time. It is for a Project Euler problem in which one is given a very large sum to find, and then required to print the first ten digits of said sum. (The problem can be found here: https://projecteuler.net/problem=13)
I have run several 'tests' where I add print commands to see various values at various points in the code. When I run the code, I have gotten anything from symbols to ten digit numbers that should be single digits.
Anyways. My question is this: is this a type conversion issue or is there some other glaring issue with my method that I'm missing? I've been studying type conversions trying to find a fix, but to no avail.
Thank you for any help!
The code is as follows:
// this is a program to find a very large sum of many very large numbers
#include <stdio.h>
#include <math.h>
int main()
{
//declare all ints needed
int i;
int j;
int d; // digit, need to add 48
int placesum; // sum of addition in _'s place (1's, 10's, 10000's)
int place; // final place value
int c = 0, tens = 1, otherc; // counters for start finder
int a = 0; // another counter
//declare all arrays
char numarray[101][51]; //array of strings containing all 100 numbers
char sum[100];
printf("please save data to largesumdata.txt\n\n press enter when ready");
getchar();
// THE PROBLEM- I don't know how to get my data into my program // FIXED
// using fscanf()
FILE *pf; // declare a pointer to the file
pf = fopen("largesumdata.txt", "r"); // trys to open file // "r" means read only
if(pf == NULL)
printf("Unable to open file, sorry Jar\n");
else
{
for(j = 0; j < 100; j++)
fscanf(pf, "%s\n", &numarray[j]); // fscanf(pointer, data type, location)
}
//TESTING
//printf("You have reached point A\n");//POINT A WAS REACHED
//TESTING
//TESTING
//printf("Check1, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("%c\n", numarray[90][22]);//Can successfully call characters from array
//TESTING
// (Brute force attempt) //I NEVER MESS WITH numarray WHY IS IT CHANGING
for(i = 49; i >= 0; i--)
{
//printf("%d\n", d);
for(j = 0; j < 100; j++)
{
d = (int)numarray[j][i] - 'o';
//printf("%d\n", d);
//holdup// d -= 48; // ASCII conversion // could also write "d = d-48"
//printf("%d\n", d);
placesum += d; // could also write "placesum = placesum + d"
//printf("%d\n", placesum);
}
place = placesum % 10;
placesum = placesum / 10; // takes "10's place" digit for next column
// now need to put 'int place' into 'char sum'
sum[i+5] = (char)place+'0'; // ASCII conversion // "+5" for extra space //HERE not properly stored in sum
}
//TESTING
//printf("Check2, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("You have reached point B\n");//POINT B WAS REACHED
//TESTING
// find out where sum starts
for(c=0; c<10; c++)
if(sum[c] != '0')
break;
//TESTING
//printf("You have reached point C\n"); //POINT C WAS REACHED
//TESTING
otherc = 4-c;
printf("The first 10 digits of the sum of all those f***ing numbers is....\n");
printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9]);
//%c-%c-%c-%c-%c-%c-%c-%c-%c-%c //copy and paste purposes
//%d-%d-%d-%d-%d-%d-%d-%d-%d-%d // ^^^^^
getchar();
return 0;
}
P.S. I apologize if my plethora of notes is confusing
You are using wrong form to print an array in C.
sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9] -> This actually decays to sum[otherc+9] because C treats , as an operator.
To print value at each array index, you should use it like this: sum[otherc], sum[otherc+1], sum[otherc+2],..
To read more about C's , (comma) operator, you can begin here
In your printf as I explained above, the first format specifier %d gets sum[otherc + 9], since sum[otherc,...,otherc+9] is actually a single number and that is otherc + 9th index of array sum. You do not provide anything to print for other format specifiers, hence you get garbage.
After a while I revisited my code, and realized that I was working with numbers upwards of 10 million. I had a mix of int, long int, and long long int variables declared.
I re-analyzed which was which, and made sure that all variables could handle the data it needed to (after looking at this handy link, showing what max integer sizes are for different data types.
Before I had been using the wrong ones, and going over the max values returned incorrect values, causing my program to crash during run time.
Lesson here: Check your data types!
Here's the situation. I have to read in data from an external binary file and display the data in order and so that it makes sense to the user.
The file has data stored as follows: the first 4 bytes are an integer, then the next 8 bytes are a floating decimal, followed by the next 8 bytes (float), etc. So I need to read in 4 bytes initially, then repeatedly 8 bytes after that... until the file has no data left to read.
I have read the file in such a way that it stores its data into an array i[NUM] (where NUM is the number of elements), and each element contains 4 bytes. By doing this, I have accidentally 'split' the floats in half, the first half being stored in i[1] and the second half in i[2], also a float in i[3] and i[4], etc.
Now I am in the process of trying to 'stitch' the two halves of each float back together again in order to display them, but I am stuck.
Any suggestions are greatly appreciated.
My code so far:
#include "stdafx.h"
#include "stdio.h"
#define NUM 15
int main(void)
{
//initialising
int i[NUM], j, k;
float temp[NUM];
char temp_c[NUM];
int element_size = 4;
int element_number = NUM;
for(k=0; k<NUM; k++)
{
i[k] = 0; //clear all cells in i[]
temp[k] = 0; //clear all cells in temp[]
}
//file reading
FILE *fp;
fp = fopen("C:\\data", "rb+");
fread(&i, element_size, element_number, fp); //reads 'data' to the end and then stores each element into array i[]
fclose(fp); //close the file
//arrange and print data here
printf("Data of File\n\nN = %d",i[0]);
//this is where the rest fell apart
//No idea how to go about it
return 0;
}
If you're sure that the float is 8 bytes and the int is 4 then you can do this (probably in a loop with variables instead of the fixed indices I've used):
memcpy(&temp[0], &i[1], 8);
I'm assuming that your code for creating the file was a fwrite where you wrote the 4-byte int, then wrote the 8-byte floats.
Then you can output the floats with printf("%f\n", temp[0]); or whatever.
NB. You can avoid your initialization loop by initializing the arrays directly: int i[NUM] = { 0 }; etc. This only works for 0, not for other values.