find which line has the most vowels from a file - c

create function int isVowel( char c )
create function int vowels( char s[] )
Which string from the file contains the most vowels
- in the case of the tie, show just the 1st
# obviously should use the functions
above is what i am trying to do but i am not entirely sure on how to actually do it i could use some hints
I'm just not entirely sure how to do this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int isvowel(char c)
{
int vowel=0;
int i;
int x=0;
//for(i=0; i<5; i++){
// counter[i]=0;}
for(i=0; i <c; i++)
{
if (c=='a' || c=='A')
vowel++;
else if (c=='e' || c=='E')
vowel++;
else if (c=='i' || c=='I')
vowel++;
else if (c=='o' || c=='O')
vowel++;
else if (c=='u' || c=='U')
vowel++;
}
return vowel;
}
int main( int argc, char *argv[] )
{
char max[1024];
char** buff;
int i=0 ,num = 5;
FILE *infile;
int lc = 0; //counts how many lines there are
int p;
//asks for file name if none is supplied
if ( argc < 2 )
{
printf("Must supply file name\n");
return 1;
}
infile = fopen( argv[1], "r" );
//checks to see if file opens
if ( infile == NULL )
{
printf("could not open %s\n", argv[1]);
return 1;
}
buff = (char**)calloc(sizeof(max),sizeof(char));
int k;
for(k=0; k<num;k++){
buff[k] = (char*)calloc(sizeof(max),sizeof(char));
}
while(fgets(max,sizeof(max),infile)){
strcpy(buff[i],max);
i++;
}
int x;
for(x =1; x<i;x++){
lc++;
printf("%d:%s",x,buff[x]);
}
p = isvowel(i);
printf("your number of vowels is:%d",p);
return 0;
}
should print a string with most vowels
right now I can't even get it to count any vowels

A character is either vowel or not:
int isVowel(char c) {
switch (c) {
case 'a':
case 'A':
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U':
return 1;
}
return 0;
}
Now, let's implement your other function:
int vowels(char s[]) {
int size = strlen(s);
int output = 0;
for (int i = 0; i < size; i++) output += isVowel(s[i]);
return output;
}

how about try this one, first, initialize the p to 0
int p = 0; // would be accumulated in another loop
and, revised the x loop,
for(x =0; x<i;x++){ // start with 0 for checking from buff[0]
lc++;
printf("%d:%s",x,buff[x]);
for(int y=0; y<sizeof(max); y++){ // add another loop
p += isvowel(buff[x][y])); // revise and move here
}
}
it would be helpful to research the "switch case" and "tolower"

I would suggest this function:
int vowel(char *s, size_t len)
{
int vowelCount = 0;
for (int i = 0; i < len; ++i)
{
switch (s[i])
{
case 'a':
case 'A':
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U':
{
++vowelCount;
break;
}
}
}
return vowelCount;
}
Ask away if something's unclear.

Related

seeking combinations (strstr) of letters in external file

I have a task to make smth like t9 like it was in old phones (number can also mean some combination of letters). For example, if user run it this way ./t9search 23 < list.txt, program should return numbers which has this combination of digits or letters that corresponds to them (in this case a,b,c and d,e,f). It's also forbidden to work with dynamic memory(malloc, free) and functions with algorithms (qsort, lsearch etc). Format of information in file is "name\n number\n name\n number\n...".
The loop doesn't work correctly but I can't find a mistake. The program should return {Name}, {number}but it return only numbers.
The code is:
`
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FULFILLED 1
#define NOT_FULFILLED 0
int main(int argc, char **argv)
{
char line[99];
int line_no = -1;
int size = strlen(argv[1]);
char letters[size][5];
int total_combinations = 1;
char combinations[total_combinations][size + 1];
int current_combination[size];
int check_name = NOT_FULFILLED;
char name[99];
for(int i = 0; argv[1][i]; i++)
{
switch(argv[1][i]) //cases according to input
{
case '0':
strcpy(letters[i], "+");
break;
case '2':
strcpy(letters[i], "abc");
break;
case '3':
strcpy(letters[i], "def");
break;
case '4':
strcpy(letters[i], "ghi");
break;
case '5':
strcpy(letters[i], "jkl");
break;
case '6':
strcpy(letters[i], "mno");
break;
case '7':
strcpy(letters[i], "pqrs");
break;
case '8':
strcpy(letters[i], "tuv");
break;
case '9':
strcpy(letters[i], "wxyz");
break;
}
total_combinations *= strlen(letters[i]); //number of combinations of letters from array elements
}
for (int i = 0; i < size; i++)
{
current_combination[i] = 0;
}
int k = 0;
while (k < total_combinations)
{
for (int set_idx = 0; set_idx < size; set_idx++)
{
int letter_idx = current_combination[set_idx];
combinations[k][set_idx] = letters[set_idx][letter_idx];
}
combinations[k][size] = '\0';
for(int i = size - 1; i >= 0; i--)
{
current_combination[i]++;
if (current_combination[i] == strlen(letters[i]))
{
current_combination[i] = 0;
}
else
{
break;
}
}
k++;
}
printf("%c\n", sizeof(combinations)/sizeof(combinations[0]));
while(fgets(line, sizeof(line), stdin))
{
line_no++;
if (line_no % 2 == 0) //even lines (names)
{
name[99] = line; //variable to use name with number
for (int i = 0; i < total_combinations; i++) //for each combination from array with combinations
{
if (strstr(line, combinations[i])) //if combination is a substring of a string
{
check_name = FULFILLED;
}
}
}
else if (line_no % 2 == 1) //odd lines (numbers)
{
if (check_name == FULFILLED || strstr(line, argv[1])) // if there's name that corresponds with input OR input is a substring of a string
{
printf("%s, %s", name, line);
check_name = NOT_FULFILLED;
}
}
}
}
`
I've tried to change the way of checking names:
if (line_no % 2 == 0)
{
for (int j = 0; j <= strlen(letters); j++)
{
char let = getchar();
for (int i = 0; i < strlen(line); i++)
{
if (letters[j] == line[i])
{
check_name = FULFILLED;
continue;
}
else if (letters[j] != line [i])
{
break;
}
}
}
}
Sure I didn't reach success. So I'd be extremely grateful for any help.
Arrays do not resize reflectively when the variables used to create them change. They are sized permanently at the time of their initialization. The following
int total_combinations = 1;
char combinations[total_combinations][size + 1];
/* ... */
total_combinations *= strlen(letters[i]);
does not cause combinations to grow as total_combinations does. Move the definition of combinations to after total_combinations has been fully computed.
The following attempts to assign a char * to a char, and also indexes name out of bounds.
name[99] = line;
As done previously, use strcpy to copy strings.
Note that, if found and if there is room in the buffer, fgets stores the newline character in the buffer, so
printf("%s, %s", name, line);
will very likely print staggered output, like
Alice
, 5551234567
A cursory refactoring:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *remove_newline(char *string)
{
if (string)
string[strcspn(string, "\n")] = '\0';
return string;
}
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "usage: %s t9_sequence\n", argv[0]);
return EXIT_FAILURE;
}
int size = strlen(argv[1]);
char letters[size][5];
int total_combinations = 1;
int current_combination[size];
for (int i = 0; argv[1][i]; i++) {
switch (argv[1][i]) {
default:
fprintf(stderr, "Invalid input: \"%c\"\n", argv[1][i]);
return EXIT_FAILURE;
case '0':
strcpy(letters[i], "+");
break;
case '2':
strcpy(letters[i], "abc");
break;
case '3':
strcpy(letters[i], "def");
break;
case '4':
strcpy(letters[i], "ghi");
break;
case '5':
strcpy(letters[i], "jkl");
break;
case '6':
strcpy(letters[i], "mno");
break;
case '7':
strcpy(letters[i], "pqrs");
break;
case '8':
strcpy(letters[i], "tuv");
break;
case '9':
strcpy(letters[i], "wxyz");
break;
}
total_combinations *= strlen(letters[i]);
}
memset(current_combination, 0, sizeof current_combination);
char combinations[total_combinations][size + 1];
for (int k = 0; k < total_combinations; k++) {
for (int set_idx = 0; set_idx < size; set_idx++) {
int letter_idx = current_combination[set_idx];
combinations[k][set_idx] = letters[set_idx][letter_idx];
}
combinations[k][size] = '\0';
for (int i = size - 1; i >= 0; i--) {
current_combination[i]++;
if (current_combination[i] != strlen(letters[i]))
break;
current_combination[i] = 0;
}
}
char name[128];
char number[128];
while (1) {
if (!fgets(name, sizeof name, stdin))
break;
if (!fgets(number, sizeof number, stdin))
break;
int found = 0;
for (int i = 0; i < total_combinations; i++) {
if (strstr(name, combinations[i])) {
found = 1;
break;
}
}
if (found || strstr(number, argv[1]))
printf("%s, %s\n", remove_newline(name), remove_newline(number));
}
}

C language: Given a string, delete/remove the words that contain the n number of vowels

Given an integer n, the program has to delete each word, that contains the n number of vowels.
The string is read from a test.txt file, which contains the following:
Astazi nu este maine.
Currently my program contains a count1 function, that counts the number of characters and vowels for each word in the string.
How can I use the data from count1 function as a refference when typing in the n vowels to delete the needed words then print the updated string?
I have an idea, which I'm unsure how to implement. In count1 we already count the number of vowels per each word, so, given n by the user we check if this number is equal to v in the count1 function and so we do int num_of_words++, then we do a loop, which prints out the needed words, until num_of_words=0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void count1 (char* str)
{
for (int i = 0;;)
for (int v = 0, w = i;;)
{
int len;
char c = str[i++];
switch (c)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
v++;
default:
continue;
case ' ':
case '\t':
case '\n':
case '\0':
len = i - 1 - w;
printf("'%.*s': %d characters, %d vowels\n", len, str+w, len, v );
if (c)
break;
else
return;
}
break;
}
}
void count2 (char* str, int n)
{
char line2[128];
int ls=strlen(str);
for (int i = 0;;)
for (int v = 0, w = i;;)
{
int len;
char c = str[i++];
switch (c)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
v++;
default:
continue;
case ' ':
case '\t':
case '\n':
case '\0':
for(int k = 0; str[k] != '\0'; k++)
{
if (k == 0 || isspace(str[k]))
{
if(v==n)
{
strcat(line2, str+1);
}
}
}
printf("%s ", line2);
if (c)
break;
else
return;
}
break;
}
}
int main()
{
FILE *fp;
char line[128];
int c=0, count[26]= {0}, x;
int n;
fp = fopen("test.txt", "r");
fscanf(fp, "%[^\n]", line);
fclose(fp);
printf("%s\n\n", line);
while (line[c] != '\0')
{
if (line[c] >= 'a' && line[c] <= 'z')
{
x = line[c] - 'a';
count[x]++;
}
c++;
}
for (c = 0; c < 26; c++)
{
printf("%c occurs %d times.\n", c + 'a', count[c]);
}
printf("\n");
count1(line);
printf("\nInsert n: ");
scanf("%d", &n);
count2(line, n);
return 0;
}
If you have a string str that consists of separate words, separated one from another by ' ' or '\n' or '\t', and you want to have a string that contains all the words in str that satisfy some condition, it will be a bit difficult to program it such that it will be "in-place", i.e. to change str to the desired string, without using a "helper array" of some sort.
Instead, I would recommend to create a new char array with the same size (say str2), and every time you find a word that satisfies the condition (the condition can be for example: doesn't have 1 vowel), you copy the word that you found from str to str2.
Something like this:
char str[128];
// read from file to str using fscanf
char str2[128];
for (int c = 0; str[c] != '\0'; ++c)
{
if (c == 0 || isspace(str[c]))
{
if (! is_1_vowel[str+1]) // if it doesn't have exacly one vowel
{
// copy the word from str to str2
strcat_word(str2, str+1); // a user-defined adapted version of strcat that will copy from src to dest only till src reaches a space character or '\0'
}
}
}
I'm assuming here that is_1_vowel will be a function that goes over a single word (and not the whole line or file), and returns 1 if it satisfies the condition (has 1 vowel), and returns 0 otherwise.
Here's my final solution
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void count1 (char* str)// count numbers of vowels for each word
{
for (int i = 0;;)
for (int v = 0, w = i;;)
{
int len;
char c = str[i++];
switch (c)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
v++;
default:
continue;
case ' ':
case '\t':
case '\n':
case '\0':
len = i - 1 - w;
printf("'%.*s': %d characters, %d vowels\n", len, str+w, len, v );
if (c)
break;
else
return;
}
break;
}
}
void print_x(char* str, int n)
{
char* tmp;
unsigned int cnt = 0, stat = 0;
const char aeiou[] = "AEIOUaeiou";
while(*str)
{
switch(stat)
{
case 0://the word did not start
if (!isalpha(*str))
{
putchar(*str);
break;
}
stat = 1;
tmp = str;
cnt = 0;
case 1://the word started
if (strchr(aeiou, *str))
{
cnt++;
break;
}
if (! isalpha(*str))
{
if (cnt != n)
while(tmp <= str) putchar(*(tmp++));
else putchar(*str);
stat = 0;
}
} // end switch
++str;
}
if (stat)
{
--str;
if (cnt != n) while(tmp <= str) putchar(*(tmp++));
}
}
int main()
{
FILE *fp;
char line[128], line2[128];
int c=0, count[26]= {0}, x;
int n,a;
int i,j;
fp = fopen("test.txt", "r");
fscanf(fp, "%[^\n]", line);
fclose(fp);
printf("%s\n\n", line);
while (line[c] != '\0')
{
if (line[c] >= 'a' && line[c] <= 'z')
{
x = line[c] - 'a';
count[x]++;
}
c++;
}
for (c = 0; c < 26; c++)
{
printf("%c occurs %d times.\n", c + 'a', count[c]);
}
for (i = 0; i < 26; ++i)
{
for (j = i + 1; j < 26; ++j)
{
if (count[i] < count[j])
{
a = count[i];
count[i] = count[j];
count[j] = a;
}
}
}
printf("\n\n");
for (c = 0; c < 26; c++)
{
printf("%c occurs %d times.\n", c + 'a', count[c]);
}
printf("\n");
count1(line);
printf("\nInsert n: ");
scanf("%d", &n);
if (!(fp = fopen("./test.txt", "r")))
{
printf("unable open file\n");
return 1;
}
while (fgets(line, 128, fp))
print_x(line, n);
fclose(fp);
return 0;
}

Why my converter doesn't count the last digit?

This program is about converting Roman number to decimal number. The program can convert the alphabet to number but it can not process the last roman digit. I think my flow is alright but the output is not right. Can any body give me a helping hand?
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int roman_to_int(const char s[], int length) {
// Please complete the function body
int ans = 0, value[length];
for (int i = 0; i < length; i++) {
switch (s[i]) {
case 'I': value[i] = 1; break;
case 'V': value[i] = 5; break;
case 'X': value[i] = 10; break;
case 'L': value[i] = 50; break;
case 'C': value[i] = 100; break;
case 'D': value[i] = 500; break;
case 'M': value[i] = 1000; break;
}
}
for (int i = 0; i < length - 1; i++) {
if (value[i] >= value[i+1])
ans += value[i];
else {
ans = ans + value[i+1] - value[i];
i++;
}
}
return ans;
}
int main() {
char roman_num[] = "III";
char roman_num_2[] = "CXXIII";
char roman_num_3[] = "MMMCDLIX";
printf("roman_to_int(%s) = %d\n", roman_num,
roman_to_int(roman_num, strlen(roman_num)));
printf("roman_to_int(%s) = %d\n", roman_num_2,
roman_to_int(roman_num_2, strlen(roman_num_2)));
printf("roman_to_int(%s) = %d\n", roman_num_3,
roman_to_int(roman_num_3, strlen(roman_num_3)));
}
You should add the value of the last roman digit after the end of the second loop.
As an alternative, you could make value on entry longer than n and set the last entry to 0 so you won't need the make a special case of the last roman digit.
Note that you should also handle the case of unrecognised roman digits: either by ignoring them or by returning an error code, such as a negative value -1.
It is also simpler for roman_to_int to take a null terminated C string and compute the length there.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int roman_to_int(const char s[]) {
// Please complete the function body
int length = strlen(s);
int ans = 0, value[length + 1];
for (int i = 0; i < length; i++) {
switch (s[i]) {
case 'I': value[i] = 1; break;
case 'V': value[i] = 5; break;
case 'X': value[i] = 10; break;
case 'L': value[i] = 50; break;
case 'C': value[i] = 100; break;
case 'D': value[i] = 500; break;
case 'M': value[i] = 1000; break;
default: return -1;
}
}
value[length] = 0;
for (int i = 0; i < length; i++) {
if (value[i] >= value[i + 1])
ans += value[i];
else
ans -= value[i];
}
return ans;
}
int main() {
char roman_num[] = "III";
char roman_num_2[] = "CXXIII";
char roman_num_3[] = "MMMCDLIX";
char roman_num_4[] = "MMMCDLIZ"; // error
printf("roman_to_int(%s) = %d\n", roman_num, roman_to_int(roman_num));
printf("roman_to_int(%s) = %d\n", roman_num_2, roman_to_int(roman_num_2));
printf("roman_to_int(%s) = %d\n", roman_num_3, roman_to_int(roman_num_3));
printf("roman_to_int(%s) = %d\n", roman_num_4, roman_to_int(roman_num_4));
return 0;
}

Segmentation Fault Error (C)

I am currently writing a program that is supposed to receive input from a text file and output statistics about the text such as the number of letters, size of words and how often they occur, and how many times each word occurs. However, every time I run the program, I get a segmentation fault error. The program runs until I hit the line Letter Count Analysis. The I receive the segmentation fault error. Here is some sample text:
1
Hello my name is Bob
I live in Canada
The number represents how many lines are supposed to be read. What should I do to correct my issue? I am very new to programming so I'm sure it is something basic.
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LENGTH 80
#define MAX_WORD_LENGTH 20
#define MAX_LINES 10
void letterAnalysis(char [][MAX_LINE_LENGTH], int lineTotal);
int wordLengthAnalysis(char [][MAX_LINE_LENGTH], int lineTotal, int wordLength);
void wordAnalysis(char [][MAX_LINE_LENGTH], int lineTotal);
int main (void){
int lineTotal, wordSize;
char text[lineTotal][MAX_LINE_LENGTH];
char n[1];
fgets(n, 10, stdin);
lineTotal = n[0] - '0';
for(int i = 0; i < lineTotal; i++){
fgets(text[i], MAX_WORD_LENGTH, stdin);
}
printf("\n***Letter count analysis***\n");
letterAnalysis(text, lineTotal);
printf("\n***Word length analysis***\n");
for (int i = 1; i <= MAX_WORD_LENGTH; i++){
wordSize = wordLengthAnalysis(text, lineTotal, i);
if (wordSize == 1){
printf("\n%-2d\tword of length %d", wordSize, i);
}
else{
printf("\n%-2d\twords of length %d", wordSize, i);
}
}
printf("\n\n***Word analysis***\n");
wordAnalysis(text, lineTotal);
return 0;
}
void letterAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal){
int alphabet[26] = {0};
for (int i = 0; i < lineTotal; i++){
for(int j = 0; j < MAX_LINE_LENGTH; j++){
switch(text[i][j]){
case 'A': case 'a':
alphabet[0]++;
break;
case 'B': case 'b':
alphabet[1]++;
break;
case 'C': case 'c':
break;
alphabet[2]++;
case 'D': case 'd':
alphabet[3]++;
break;
case 'E': case 'e':
alphabet[4]++;
break;
case 'F': case 'f':
alphabet[5]++;
break;
case 'G': case 'g':
alphabet[6]++;
break;
case 'H': case 'h':
alphabet[7]++;
break;
case 'I': case 'i':
alphabet[8]++;
break;
case 'J': case 'j':
alphabet[9]++;
break;
case 'K': case 'k':
alphabet[10]++;
break;
case 'L': case 'l':
alphabet[11]++;
break;
case 'M': case 'm':
alphabet[12]++;
break;
case 'N': case 'n':
alphabet[13]++;
break;
case 'O': case 'o':
alphabet[14]++;
break;
case 'P': case 'p':
alphabet[15]++;
break;
case 'Q': case 'q':
alphabet[16]++;
break;
case 'R': case 'r':
alphabet[17]++;
break;
case 'S': case 's':
alphabet[18]++;
break;
case 'T': case 't':
alphabet[19]++;
break;
case 'U': case 'u':
alphabet[20]++;
break;
case 'V': case 'v':
alphabet[21]++;
break;
case 'W': case 'w':
alphabet[22]++;
break;
case 'X': case 'x':
alphabet[23]++;
break;
case 'Y': case 'y':
alphabet[24]++;
break;
case 'Z': case 'z':
alphabet[25]++;
break;
}
}
}
for(int i = 0; i <= 25; i++){
printf("%c: \t%d\n",'a' + i, alphabet[i]);;
}
}
int wordLengthAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal, int wordLength){
int sentenceLength;
int counter, wordSize = 0;
for(int i = 0; i < lineTotal; i++){
sentenceLength = strlen(&text[i][0]);
for(int j = 0; j < sentenceLength + 2; j++){
if(text[i][j] == ' '){
if(counter == wordLength){
++wordSize;
counter = 0;
}
else{
counter = 0;
}
}
else{
counter++;
}
}
}
return wordSize;
}
void wordAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal){
char maxWords[800];
char word[MAX_LINE_LENGTH], word2[MAX_WORD_LENGTH], *ptrText, *ptrTextCounter;
int counter, textCounter = 0;
int sentenceLength, wordTracker;
int lineFlag;
for(int i = 0; i < lineTotal; i++){
ptrText = &text[i][0];
sentenceLength = strlen(ptrText);
counter = 0;
for (int j = 0; j < sentenceLength + 1; j++){
wordTracker = 1;
if (text[i][j] == ' ' ){
if (counter != 0){
sprintf(word, "%.*s", counter, ptrText);
ptrTextCounter = &text[i][j+1];
lineFlag = j;
if(strstr(maxWords, word) == NULL){
for (int k = i; k < lineTotal; k++){
textCounter = 0;
if (lineFlag == j){
ptrTextCounter = &text[i][j+1];
}
else{
lineFlag = 0;
ptrTextCounter = &text[i][j+1];
}
for ( ; lineFlag < sentenceLength; lineFlag++){
if(text[k][lineFlag] == ' '){
if (textCounter != 0){
if(textCounter == counter){
sprintf(word2, "%.*s", textCounter, ptrTextCounter);
if(strcmp(word, word2) == 0){
wordTracker++;
}
}
ptrTextCounter = &text[k][lineFlag];
textCounter = 0;
}
else{
ptrTextCounter = &text[k][lineFlag+1];
}
}
else{
textCounter++;
}
}
}
if(wordTracker == 1){
printf("\n\"%.*s\"\t\tappeared %d time", counter, ptrText, wordTracker);
}
else{
printf("\n\"%.*s\"\t\tappeared %d time", counter, ptrText, wordTracker);
}
}
strcat(maxWords, word);
ptrText = &text[i][j+1];
counter = 0;
}
else{
ptrText = &text[i][j+1];
}
}
else{
counter++;
}
}
}
}
I get a couple of warnings:
main.c:17:14: warning: variable length array used [-Wvla]
char text[lineTotal][MAX_LINE_LENGTH];
^
main.c:17:15: warning: variable 'lineTotal' is uninitialized when used here [-Wuninitialized]
char text[lineTotal][MAX_LINE_LENGTH];
^~~~~~~~~
You haven't initialized lineTotal but are using it. This causes undefined behavior.
main.c:64:21: warning: code will never be executed [-Wunreachable-code]
alphabet[2]++;
^~~~~~~~
Your break; is likely misplaced.
main.c:152:20: warning: variable 'counter' may be uninitialized when used here [-Wconditional-uninitialized]
if(counter == wordLength){
^~~~~~~
Again, you're using a potentially uninitialized variable.
Also:
char n[1];
fgets(n, 10, stdin);
Your array has one element but you tell fgets it can access up to n[10].
Hint (if it wasn't obvious already): never program C without warnings.

How to convert a 2D char array to a 2D int in c

I am writing a program that takes in a sudoku board that uses A-I instead of 1-9 and checks if the board is valid.
I read the sudoku board from a file and i used the switch to change all values to numbers.
My plan was to use atoi or sscanf to convert the 2D char array to a 2D int array so that i can add all the rows and columns to check if it is a valid board. However when using these functions i get the warnings:
expected type const char but argument is of type char or passing argumet one of sscanf makes pointer from integer without cast.
I'm still quite confused on pointers so idk what this really means. is it even possible to change my 2d char array to a 2d int array, if so any suggestions? if there is a better way to check if the board is valid suggestions would be greatly appreciated as well. Thanks
int main() {
int i, j;
char **matsudoku = malloc(9*sizeof(char*));
for (i=0; i<9; ++i)
matsudoku[i]=malloc(9*sizeof(char));
FILE *fpointer = fopen("C:/Users/Owner/Documents/Como Sci in C/sudokuchar.txt", "r");
if (fpointer == NULL) {
printf("Cannot open file \n");
exit(0);
}
for(i=0; i<9; i++){
for(j=0; j<9; j++){
fscanf(fpointer, " %c", &matsudoku[i][j]);
switch (matsudoku[i][j]){
case 'A':
matsudoku[i][j]='1';
break;
case 'B':
matsudoku[i][j]='2';
break;
case 'C':
matsudoku[i][j]='3';
break;
case 'D':
matsudoku[i][j]='4';
break;
case 'E':
matsudoku[i][j]='5';
break;
case 'F':
matsudoku[i][j]='6';
break;
case 'G':
matsudoku[i][j]='7';
break;
case 'H':
matsudoku[i][j]='8';
break;
case 'I':
matsudoku[i][j]='9';
break;
}
printf("%c",matsudoku[i][j]);
}
}
//atoi(matsudoku);
int k;
//or sscanf(matsudoku,"%d",%k);
fclose(fpointer);
}
I prefer this method without an atoi or a switch/case but instead exploits the nature of the ASCII table very directly. Simply read in a character but then subtract 'A'. So if the character was an 'A', then 'A' - 'A' is 0. But you mean this to be the "1" and thus, you add 1 here.
int main() {
int i, j;
char nextchar;
int **matsudoku = malloc(9*sizeof(int*));
for (i=0; i<9; ++i)
matsudoku[i]=malloc(9*sizeof(int));
FILE *fpointer = fopen("C:/Users/Owner/Documents/Como Sci in C/sudokuchar.txt", "r");
if (fpointer == NULL) {
printf("Cannot open file \n");
exit(0);
}
for(i=0; i<9; i++){
for(j=0; j<9; j++){
fscanf(fpointer, " %c", &nextchar);
matsodoku[i][j] = (int)(nextchar-'A') + 1;
printf("%d",matsudoku[i][j]);
}
}
fclose(fpointer);
}
There is really no reason to use a pointer-to-pointer-to-char to begin with when you can read the values directly into a 2D array of int. While there are many ways to approach this, sticking with your approach, you could simply do the following... read/validate each character from your file into a tmp value and then assign to matsudoku[i][j] = tmp - '0'; which will perform the character conversion in one step.
Putting it together, you could do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#define SDKSZ 9
int main (void)
{
int i, j;
int matsudoku[SDKSZ][SDKSZ] = {{0}};
FILE *fpointer =
fopen ("C:/Users/Owner/Documents/Como Sci in C/sudokuchar.txt", "r");
if (fpointer == NULL) {
printf ("Cannot open file \n");
exit (0);
}
for (i = 0; i < SDKSZ; i++)
for (j = 0; j < SDKSZ; j++) {
int tmp;
if (fscanf(fpointer, " %d", &tmp) != 1) { /* read/validate tmp */
fprintf (stderr, "error: on read matsudoku[%d][%d]\n", i, j);
exit (1);
}
matsudoku[i][j] = tmp - '0'; /* convert from ASCII to numeric */
}
fclose (fpointer);
for (i = 0; i < SDKSZ; i++) {
for (j = 0; j < SDKSZ; j++)
printf (" %3d", matsudoku[i][j]);
putchar ('\n');
}
return 0;
}
Let me know if you have any questions or problems (I didn't have data to test).
Instead of converting the letter characters to number characters, I'd make a new 2D array of type int:
int matSudokuInt[9][9];
for(i=0; i<9; i++)
{
for(j=0; j<9; j++)
{
fscanf(fpointer, " %c", &matsudoku[i][j]);
switch (matsudoku[i][j])
{
case 'A':
matSudokuInt[i][j]=1;
break;
case 'B':
matSudokuInt[i][j]=2;
break;
case 'C':
matSudokuInt[i][j]=3;
break;
case 'D':
matSudokuInt[i][j]=4;
break;
case 'E':
matSudokuInt[i][j]=5;
break;
case 'F':
matSudokuInt[i][j]=6;
break;
case 'G':
matSudokuInt[i][j]=7;
break;
case 'H':
matSudokuInt[i][j]=8;
break;
case 'I':
matSudokuInt[i][j]=9;
break;
}
printf("%d ", matSudokuInt[i][j]);
}
printf("\n");
}
Then it becomes easy to sum the rows and columns:
int sum = 0;
int rowSum[9];
int colSum[9];
// Let i be the column index and j be the row index
for (j = 0; j < 9; j++) {
sum = 0;
for (i = 0; i < 9; i++) {
sum += matSudokuInt[i][j];
}
rowSum[j] = sum;
}
for (i = 0; i < 9; i++) {
sum = 0;
for (j = 0; j < 9; j++) {
sum += matSudokuInt[i][j];
}
colSum[i] = sum;
}
You can then easily look through the sum arrays and check that all entries are equal.

Resources