Hello I am taking an intro to C-programming class so I am using very basic codes. Here I am simply trying to get a matrix of the commas out of the main string. However when I try running the program it keeps crashing on me and I don't know what is my problem. I was able to use the fgets function correctly so I think that is working fine still.
CD Data.txt File
Eagles, Hotel California, 1976, Rock, 4
The Fratellis, Costello Music, 2006, Garage Rock, 5
Awolnation, Megalithic Symphony, 2011, Indie Rock, 5
Lindsey Stirling, Lindsey Stirling, 2012, Classical Crossover, 5
Arctic Monkeys, AM, 2013, Indie Rock, 4
Program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define row 1000
#define column 1000
void getCommas(char str[], int commas[])
{
int flag, count, index;
count = 0;
index = 0;
flag = 1;
while(flag = 1)
{
if(str[count] = ',')
{
commas[index] = count;
index = index + 1;
}
count = count + 1;
if(str[count] = '\0')
{
flag = 0;
}
}
}
int main()
{
int i;
char CdInfo[row][column];
int Index[row][column];
FILE *fp;
fp = fopen("CD Data.txt","r");
for(i=0; i<5; i++)
{
fgets(CdInfo[i], sizeof CdInfo, fp);
//printf("%s\n",CdInfo[i]);
}
for (i=0; i<5; i++)
{
getCommas(CdInfo[i], Index[i]);
}
fclose(fp);
return 0;
}
These two variables are too big to be on the stack:
int main()
{
int i;
char CdInfo[row][column]; //<<
int Index[row][column]; //<<
declare them as static or as global variables.
And:
while(flag = 1)
should be
while(flag == 1)
and all
if (str[count] = ...
should be
if(str[count] == ...
You should also think about replacing
while(flag = 1) {
with :
while(flag == 1)
// note:
// the code is not making any use of more than one line of the
// input file at any one time, so
// only the current row actually needs to be defined
// note:
// this code makes no check for max length of each row (1000 char)
// that could/will be a problem when the input line is longer than 1000 character
// to avoid the error of writing an assignment rather than a literal,
// place the literal on the left side,
// then the compiler will notify you of the error
// rather than you having to spend time debugging the code
// trying to find the error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define row 1000
#define column 1000
//void getCommas(char str[], int commas[])
void getCommas( char * pStr, int * pCommas )
{
//int flag, count, index;
//count = 0;
//index = 0;
//flag = 1;
int flag = 1;
int count = 0;
int index = 0;
//while(flag = 1)
// following while loop could eliminate
// the 'flag' variable and related code by using
// and would be safer because never looking at string termination
// character but once.
// while( '\0' != pStr[count] )
while( 1 == flag )
{
//if(str[count] = ',')
if( ',' == pStr[count] )
{
pCommas[index] = count;
index = index + 1;
}
count = count + 1;
//if(str[count] = '\0')
if( '\0' == pStr[count] )
{ // then found end of string
flag = 0;
}
}
}
char CdInfo[row][column];
int Index[row][column];
int main()
{
int i = 0;
int rowCount = 0;
//char CdInfo[row][column]; // this is a huge item on the stack,
//int Index[row][column]; // this is a huge item on the stack,
//FILE *fp;
FILE *fp = NULL;
fp = fopen("CD Data.txt","r");
// always check the result of calls to io functions
if ( NULL == fp )
{ // then fopen failed
perror( "fopen" );
exit(1);
}
// implied else
// there is no reasonable reason (in the real world)
// to expect the input to be only 5 lines
//for(i=0; i<5; i++)
//{
// fgets(CdInfo[i], sizeof CdInfo, fp);
// //printf("%s\n",CdInfo[i]);
//}
for( i=0; i<row; i++ )
{
// following line checks results of call to I/O function
if( 0 == fgets( CdInfo[i], row, fp ) ) { break; }
// above line exits loop on end of file or I/O error
rowCount++;
}
//for (i=0; i<5; i++)
for( i = 0; i < rowCount; i++ )
{
getCommas(CdInfo[i], Index[i]);
}
fclose(fp);
return 0;
}
Related
I want to store a group of arrays containing 2 numbers in an array. But I only want 2 numbers to be stored when 5 followed by a comma and another number is entered. Essentially, what I want my program to do is read from this array of arrays and perform tasks accordingly. So if the user enters 2, I want to store (2,0) in one space of my array and move on to ask my user for the second number. But if the user types 5,10 I want the program to store (5,10) in that same array. Then my program could filter which array has only one value and which has 2 and do different tasks accordingly. My assignment requires us to not ask 2 numbers for each array which would have made it easier.
This is what I have so far and I know I'm wrong I just don't know where to go from here:
int main(void)
{
int size = 0;
int input;
int factor;
int mdArrays[100][2];
for (size_t i = 0; i < 100; i++)
{
size = i;
scanf("%d,%d", &input, &factor);
if (input != 5 && input != 9)
{
factor = 0;
for (size_t j =0 ; j< 2; j++)
{
mdArrays[i] = input;
mdArrays[j] = factor;
}
}
else if (input == 9)
{
break;
}
else
{
for(int j = 0; j< 2; j++)
{
mdArrays[i] = input;
mdArrays[j] = factor;
}
}
}
for (size_t i =0; i < size; i++)
{
for(size_t j = 0; j < 2; j++)
{
printf("%d,%d", mdArrays[i[j]]);
}
}
}
There were a few issues.
size is one too short (it should be i + 1).
It may be possible to handle 5 vs 5,23 using scanf. But, I prefer to use fgets and strtol and check the delimiter (e.g. whether it's , or not).
The if/else ladder logic can be simplified if we make the first test against input == 9 to stop the loop.
According to your code, you want to force a factor of zero if input != 5. That doesn't make much sense to me, but I've kept that logic [for now].
That may not be what you want/need, but it was my best interpretation of your code. The main purpose is to differentiate how many numbers are on a given line. So, adjust the rest as needed.
I think the way you're storing/displaying the array is incorrect. I believe you want to store input into mdArrays[i][0] and factor into mdArrays[i][1]. Using j makes no sense to me.
As I mentioned [in my top comments], the printf in the final loop is invalid.
Note that the code is cleaner if we don't hardwire the dimensions with a literal 100 in multiple places (e.g. once in the myArrays declaration and again in the outer for loop). Better to use (e.g.) #define MAXCOUNT 100 and replace 100 elsewhere with MAXCOUNT (see below).
I created three versions. One that is annotated with original and fixed code. Another that removes the original code. And, a third that organizes the data using a struct.
Here's the refactored code. I've bracketed your/old code [vs. my/new code] with:
#if 0
// old code
#else
// new code
#endif
I added a debug printf. Anyway, here's the code with some annotations:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int size = 0;
int input;
int factor;
int mdArrays[100][2];
for (size_t i = 0; i < 100; i++) {
#if 0
size = i;
scanf("%d,%d",&input,&factor);
#else
// get line
char buf[100];
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// strip newline -- only needed for debug print
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
// decode first number
input = strtol(buf,&cp,10);
// decode second number if it exists -- otherwise, use a sentinel
if (*cp == ',')
factor = strtol(cp + 1,&cp,10);
else
factor = -1;
printf("DEBUG: buf='%s' input=%d factor=%d\n",buf,input,factor);
#endif
// stop input if we see the end marker
if (input == 9)
break;
// remember number of array elements
size = i + 1;
// only use a non-zero factor if input is _not_ 5
if (input != 5) {
factor = 0;
#if 0
for (size_t j = 0; j < 2; j++) {
mdArrays[i] = input;
mdArrays[j] = factor;
}
continue;
#endif
}
#if 0
for (int j = 0; j < 2; j++) {
mdArrays[i] = input;
mdArrays[j] = factor;
}
#else
mdArrays[i][0] = input;
mdArrays[i][1] = factor;
#endif
}
for (size_t i = 0; i < size; i++) {
#if 0
for (size_t j = 0; j < 2; j++) {
printf("%d,%d",mdArrays[i[j]]);
}
#else
printf("%d,%d\n",mdArrays[i][0],mdArrays[i][1]);
#endif
}
return 0;
}
Here's the sample input I used to test:
5,3
7,6
8,9
5,37
5
9,23
Here's the program output:
DEBUG: buf='5,3' input=5 factor=3
DEBUG: buf='7,6' input=7 factor=6
DEBUG: buf='8,9' input=8 factor=9
DEBUG: buf='5,37' input=5 factor=37
DEBUG: buf='5' input=5 factor=-1
DEBUG: buf='9,23' input=9 factor=23
5,3
7,0
8,0
5,37
5,-1
Here's a slightly cleaned up version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOUNT 100
int
main(void)
{
int size = 0;
int input;
int factor;
int mdArrays[MAXCOUNT][2];
for (size_t i = 0; i < MAXCOUNT; i++) {
// get line
char buf[100];
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// strip newline -- only needed for debug print
#ifdef DEBUG
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
#endif
// decode first number
input = strtol(buf,&cp,10);
// decode second number if it exists -- otherwise, use a sentinel
if (*cp == ',')
factor = strtol(cp + 1,&cp,10);
else
factor = -1;
#ifdef DEBUG
printf("DEBUG: buf='%s' input=%d factor=%d\n",buf,input,factor);
#endif
// stop input if we see the end marker
if (input == 9)
break;
// remember number of array elements
size = i + 1;
// only use a non-zero factor if input is _not_ 5
if (input != 5)
factor = 0;
mdArrays[i][0] = input;
mdArrays[i][1] = factor;
}
for (size_t i = 0; i < size; i++)
printf("%d,%d\n",mdArrays[i][0],mdArrays[i][1]);
return 0;
}
You might benefit from using a struct [YMMV], so here's a version that keeps things organized that way:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOUNT 100
typedef struct {
int input;
int factor;
} data_t;
int
main(void)
{
int size = 0;
data_t mdArrays[MAXCOUNT];
data_t *data;
for (size_t i = 0; i < MAXCOUNT; i++) {
// get line
char buf[100];
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// strip newline -- only needed for debug print
#ifdef DEBUG
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
#endif
data = &mdArrays[i];
// decode first number
data->input = strtol(buf,&cp,10);
// decode second number if it exists -- otherwise, use a sentinel
if (*cp == ',')
data->factor = strtol(cp + 1,&cp,10);
else
data->factor = -1;
#ifdef DEBUG
printf("DEBUG: buf='%s' input=%d factor=%d\n",buf,input,factor);
#endif
// stop input if we see the end marker
if (data->input == 9)
break;
// remember number of array elements
size = i + 1;
// only use a non-zero factor if input is _not_ 5
if (data->input != 5)
data->factor = 0;
}
for (size_t i = 0; i < size; i++) {
data = &mdArrays[i];
printf("%d,%d\n",data->input,data->factor);
}
return 0;
}
Read a line of user input with fgets() and then parse it to see if it is one number, two comma separated numbers or something else.
I recommend using `"%n" to detect when and how scanning finished.
int get_numbers(int *input, int *factor) {
char buf[80];
if (fgets(buf, sizeof buf, stdin)) {
int n = 0;
sscanf(buf, "%d %n", input, &n);
if (n > 0 && buf[n] == '\0') return 1;
n = 0;
sscanf(buf, "%d ,%d %n", input, factor, &n);
if (n > 0 && buf[n] == '\0') return 2;
return 0; // Invalid input
}
return EOF; // No input
}
Usage
// scanf("%d,%d", &input, &factor);
switch (get_numbers(&input, &factor)) {
case 2: printf("%d %d\n", input, factor); break;
case 1: printf("%d\n", input); break;
case 0: printf("Invalid input\n"); break;
case EOF: printf("No input\n"); break;
}
I am self teaching C programming.
I am trying to count number of int present in given string which are separated by space.
exp:
input str = "1 2 11 84384 0 212"
output should be: 1, 2, 11, 84384, 0, 212
total int = 6
When I try. It gives me all the digits as output which make sense since I am not using a right approach here.
I know in python I can use str.split (" ") function which can do my job very quickly.
But I want to try something similar in C. Trying to create my own split method.
#include <stdio.h>
#include <string.h>
void count_get_ints(const char *data) {
int buf[10000];
int cnt = 0, j=0;
for (int i=0; i<strlen(data); i++) {
if (isspace(data[i] == false)
buf[j] = data[i]-'0';
j++;
}
printf("%d", j);
}
// when I check the buffer it includes all the digits of the numbers.
// i.e for my example.
// buf = {1,2,1,1,8,4,3,8,4,0,2,1,2}
// I want buf to be following
// buf = {1,2,11,84384,0,212}
I know this is not a right approach to solve this problem. One way to keep track of prev and dynamically create a memory using number of non space digits encountered.
But I am not sure if that approach helps.
You want to build your number incrementally until you hit a space, then put that into the array. You can do this by multiplying by 10 then adding the next digit each time.
void count_get_ints(const char *data) {
int buf[10000];
int j = 0;
int current_number = 0;
// Move this outside the loop to eliminate recalculating the length each time
int total_length = strlen(data);
for (int i=0; i <= total_length; i++) {
// Go up to 1 character past the length so you
// capture the last number as well
if (i == total_length || isspace(data[i])) {
// Save the number, and reset it
buf[j++] = current_number;
current_number = 0;
}
else {
current_number *= 10;
current_number += data[i] - '0';
}
}
}
I think strtok will provide a cleaner solution, unless you really want to iterate over every char in the string. It has been a while since I did C, so please excuse any errors in the code below, hopefully it will give you the right idea.
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[19] = "1 2 11 84384 0 212";
const char s[2] = " ";
char *token;
int total;
total = 0;
token = strtok(str, s);
while (token != NULL) {
printf("%s\n", token);
total += atoi(token);
token = strtok(NULL, s);
}
printf("%d\n", total);
return 0;
}
You can check the ascii value of each character by doing c-'0'. If it's between [0,9], then it's an integer. By having a state variable, when you're inside an integer by checking if a given character is a number of space, you can keep track of the count by ignoring white space. Plus you don't need a buffer, what happens if data is larger than 10,000, and you write pass the end of the buffer?, undefined behavior will happen. This solution doesn't require a buffer.
Edit, the solution now prints the integers that are in the string
void count_get_ints(const char *data) {
int count = 0;
int state = 0;
int start = 0;
int end = 0;
for(int i = 0; i<strlen(data); i++){
int ascii = data[i]-'0';
if(ascii >= 0 && ascii <= 9){
if(state == 0){
start = i;
}
state = 1;
}else{
//Detected a whitespace
if(state == 1){
count++;
state = 0;
end = i;
//Print the integer from the start to end spot in data
for(int j = start; j<end; j++){
printf("%c",data[j]);
}
printf(" ");
}
}
}
//Check end
if(state == 1){
count++;
for(int j = start; j<strlen(data); j++){
printf("%c",data[j]);
}
printf(" ");
}
printf("Number of integers %d\n",count);
}
I believe the standard way of doing this would be using sscanf using the %n format specifier to keep track of how much of the string is read.
You can start with a large array to read into -
int array[100];
Then you can keep reading integers from the string till you can't read anymore or you are done reading 100.
int total = 0;
int cont = 0;
int ret = 1;
while(ret == 1 && total < 100) {
ret = sscanf(input, "%d%n", &array[total++], &cont);
input += cont;
}
total--;
printf("Total read = %d\n", total);
and array contains all the numbers read.
Here is the DEMO
Example using strtol
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
int count_get_ints(int output[], int output_size, const char *input) {
const char *p = input;
int cnt;
for(cnt = 0; cnt < output_size && *p; ++cnt){
char *endp;
long n;
errno = 0;
n = strtol(p, &endp, 10);
if(errno == 0 && (isspace((unsigned char)*endp) || !*endp) && INT_MIN <= n && n <= INT_MAX){
output[cnt] = n;
while(isspace((unsigned char)*endp))
++endp;//skip spaces
p = endp;//next parse point
} else {
fprintf(stderr, "invalid input '%s' in %s\n", p, __func__);
break;
}
}
return cnt;
}
int main(void) {
const char *input = "1 2 11 84384 0 212";
int data[10000];
int n = sizeof(data)/sizeof(*data);//number of elements of data
n = count_get_ints(data, n, input);
for(int i = 0; i < n; ++i){
if(i)
printf(", ");
printf("%d", data[i]);
}
puts("");
}
Assuming you don't have any non-numbers in your string, you can just count the number of spaces + 1 to find the number of integers in the string like so in this pseudo code:
for(i = 0; i < length of string; i++) {
if (string x[i] == " ") {
Add y to the list of strings
string y = "";
counter++;
}
string y += string x[i]
}
numberOfIntegers = counter + 1;
Also, this reads the data between the white spaces. Keep in mind this is pseudo code, so the syntax is different.
I have a .csv file that reads like:
SKU,Plant,Qty
40000,ca56,1245
40000,ca81,12553.3
40000,ca82,125.3
45000,ca62,0
45000,ca71,3
45000,ca78,54.9
Note: This is my example but in reality this has about 500,000 rows and 3 columns.
I am trying to convert these entries into a 2D array so that I can then manipulate the data. You'll notice that in my example I just set a small 10x10 matrix A to try and get this example to work before moving on to the real thing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *getfield(char *line, int num);
int main() {
FILE *stream = fopen("input/input.csv", "r");
char line[1000000];
int A[10][10];
int i, j = 0;
//Zero matrix
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
A[i][j] = 0;
}
}
for (i = 0; fgets(line, 1000000, stream); i++) {
while (j < 10) {
char *tmp = strdup(line);
A[i][j] = getfield(tmp, j);
free(tmp);
j++;
}
}
//print matrix
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
printf("%s\t", A[i][j]);
}
printf("\n");
}
}
const char *getfield(char *line, int num) {
const char *tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",\n"))
{
if (!--num)
return tok;
}
return 0;
}
It prints only "null" errors, and it is my belief that I am making a mistake related to pointers on this line: A[i][j] = getfield(tmp, j). I'm just not really sure how to fix that.
This is work that is based almost entirely on this question: Read .CSV file in C . Any help in adapting this would be very much appreciated as it's been a couple years since I last touched C or external files.
It looks like commenters have already helped you find a few errors in your code. However, the problems are pretty entrenched. One of the biggest issues is that you're using strings. Strings are, of course, char arrays; that means that there's already a dimension in use.
It would probably be better to just use a struct like this:
struct csvTable
{
char sku[10];
char plant[10];
char qty[10];
};
That will also allow you to set your columns to the right data types (it looks like SKU could be an int, but I don't know the context).
Here's an example of that implementation. I apologize for the mess, it's adapted on the fly from something I was already working on.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Based on your estimate
// You could make this adaptive or dynamic
#define rowNum 500000
struct csvTable
{
char sku[10];
char plant[10];
char qty[10];
};
// Declare table
struct csvTable table[rowNum];
int main()
{
// Load file
FILE* fp = fopen("demo.csv", "r");
if (fp == NULL)
{
printf("Couldn't open file\n");
return 0;
}
for (int counter = 0; counter < rowNum; counter++)
{
char entry[100];
fgets(entry, 100, fp);
char *sku = strtok(entry, ",");
char *plant = strtok(NULL, ",");
char *qty = strtok(NULL, ",");
if (sku != NULL && plant != NULL && qty != NULL)
{
strcpy(table[counter].sku, sku);
strcpy(table[counter].plant, plant);
strcpy(table[counter].qty, qty);
}
else
{
strcpy(table[counter].sku, "\0");
strcpy(table[counter].plant, "\0");
strcpy(table[counter].qty, "\0");
}
}
// Prove that the process worked
for (int printCounter = 0; printCounter < rowNum; printCounter++)
{
printf("Row %d: column 1 = %s, column 2 = %s, column 3 = %s\n",
printCounter + 1, table[printCounter].sku,
table[printCounter].plant, table[printCounter].qty);
}
// Wait for keypress to exit
getchar();
}
There are multiple problems in your code:
In the second loop, you do not stop reading the file after 10 lines, so you would try and store elements beyond the end of the A array.
You do not reset j to 0 at the start of the while (j < 10) loop. j happens to have the value 10 at the end of the initialization loop, so you effectively do not store anything into the matrix.
The matrix A should be a 2D array of char *, not int, or potentially an array of structures.
Here is a simpler version with an allocated array of structures:
#include <stdio.h>
#include <stdlib.h>
typedef struct item_t {
char SKU[20];
char Plant[20];
char Qty[20];
};
int main(void) {
FILE *stream = fopen("input/input.csv", "r");
char line[200];
int size = 0, len = 0, i, c;
item_t *A = NULL;
if (stream) {
while (fgets(line, sizeof(line), stream)) {
if (len == size) {
size = size ? size * 2 : 1000;
A = realloc(A, sizeof(*A) * size);
if (A == NULL) {
fprintf(stderr, "out of memory for %d items\n", size);
return 1;
}
}
if (sscanf(line, "%19[^,\n],%19[^,\n],%19[^,\n]%c",
A[len].SKU, A[len].Plant, A[len].Qty, &c) != 4
|| c != '\n') {
fprintf(stderr, "invalid format: %s\n, line);
} else {
len++;
}
}
fclose(stream);
//print matrix
for (i = 0; i < len; i++) {
printf("%s,%s,%s\n", A[i].SKU, A[i].Plant, A[i].Qty);
}
free(A);
}
return 0;
}
I am trying to open an file that has many lines of numbers in it, then convert it from a string into an integer.
I would like to do this without using any library functions, so no atoi, no strtol nor strtoul.
This is what my code looks like:
#include <stdio.h>
#include <stdlib.h> /* required for atoi. */
int main(void) {
int i, len;
int result=0;
double numbers;
char num[20]; /* declares a char array. */
FILE *file; /* declare a file pointer. */
file = fopen("test22.txt", "r"); /* opens the text file for reading only, not writing. */
while(fgets(num, 100, file)!=NULL) { /* this while loop makes it so that it will continue looping until the value is null, which is the very end. */
len=strlen(num);
for(i=0; i<len; i++) {
result = result*10 + ( num[i] - '0' );
}
printf("%d\n", result);
}
fclose(file); /* closes the file */
return 0;
}
Right now it's returning numbers that are not present in the text file.
Any help would be appreciated! Thanks!
You're not resetting result to zero with each new line, so it just keeps accumulating. Change
while(fgets(num, 100, file)!=NULL) {
len=strlen(num);
for(i=0; i<len; i++) {
result = result*10 + ( num[i] - '0' );
}
printf("%d\n", result);
}
to
while(fgets(num, 100, file)!=NULL) {
result = 0;
len=strlen(num);
// account for newline - should really be smarter than this.
// I'll leave that as an exercise for the reader... ;)
for(i=0; i< (len - 1); i++) {
result = result*10 + ( num[i] - '0' );
}
printf("%d\n", result);
}
The function fgets retains the newline at the end of the string (if present), which you are trying to convert as a digit. I suggest a loop like this:
for(i=0; i<len && isdigit(num[i]); i++)
and you must also have
result = 0;
for(i=0; i<len && isdigit(num[i]); i++)
before each loop.
Note that you cannot just reduce the result of strlen because the last line of the file may not have a newline at its end.
Edit: since you posted a file with negative numbers, here is an example that will convert them.
#include <stdio.h>
#include <ctype.h>
int getnum(char *str)
{
int result = 0;
int neg = 0;
if(*str == '-') {
neg = 1;
str++;
}
while(isdigit(*str)) {
result = result * 10 + *str - '0';
str++;
}
if(neg) {
return -result;
}
return result;
}
int main(void)
{
printf("%d\n", getnum("123456789\n"));
printf("%d\n", getnum("-987654321\n"));
return 0;
}
Program output:
123456789
-987654321
I need to write a C program that counts the number of characters and digits in a file. I believe my best attempt is close, but the program must call a given function, mostfrequent(), and I cannot figure out how to implement it into my main so that they work together. Any help would be greatly appreciated. Thank you.
// this is the function my program is required to use.
int mostfrequent(int *a, int length) {
int index = 0;
int max = a[0];
int i;
for (i = 1; i < length; i++) {
if (a[i] > max) {
max = a[i];
index = i;
}
}
return index;
}
// this is my closest attempt at a working program so far, but it does
// not call mostfrequent() which I need it to do.
int main() {
typedef FILE *ptr_file;
int x, i, j;
int length;
char c;
char ch[1000];
int a = 65;
c = getc(ptr_file);
ptr_file = fopen("file.txt", "r");
if (!ptr_file)
return 1;
while (c != EOF) {
scanf(ptr_file, "%s", ch[i]);
i++;
fclose(ptr_file);
}
for (i = 0; i < length; i++) {
for (j = 0; j < length; j++) {
if (a < 116) {
if (char(a) == 'ch[j]')
char max_char_temp=(char)a
count_temp++;
}
if (count_temp > count) {
count = count_temp;
max_char = max_char_temp;
}
return 0;
}
regarding the question: when to call the most_frequent() function.
After you have created an array (which would be 36 entries long of integers), initialize that array to all zeros, then incremented the appropriate entry for each character read from the input file. (note 36 entries allows for a...z + 0...9 so all other characters read from the file should be discarded.
Then pass the array and 36 to the most_frequent() function
then code similar to the following could do the job:
#include <stdio.h>
#include <stdlib.h>
#include <ctypes.h> // isalpha(), isdigit(), toupper()
#define NUM_ALPHA (26)
int main( void )
{
int array[36] = {'\0'};
//...open file, etc
//then assure all processed characters are upper case or numeric
// and update the count in the array
int ch;
while( ch = getc( file ) != EOF && '\n' != ch)
{
if ( isalpha(ch) )
{
ch = toupper(ch);
array[ch - 'A']++;
}
else if (isdigit(ch) )
{
array[ (ch-'0') + NUM_ALPHA ]++;
}
}
int index = mostfrequent( array, sizeof(array)/sizeof(array[0]);
//... do what is needed with 'index' for instance
printf( "the highest occurring char is:" );
if( index < NUM_ALPHA )
{
printf( "%c\n", index+'A' );
}
else
{
printf( "%d\n", (index-NUM_ALPHA)+'0');
}
fclose( file );
return 0;
}
however, note that mostfrequent() only returns the index to the first entry encountered with the max value, when there are multiple entries with the same max value.