can't assign character when while loop is done in C - c

I am trying to find solution how to add '\0' at the end of string (array of characters in C ).
I already have array "number" which is generated from for loop.
int i=0;
int j=0;
char s[] = "123.45e-10";
while (s[i] != '\0') {
if (isdigit(s[i]) && eFound == false) {
number[j++] = s[i];
}
i++
}
I tried to do this:
i = 0;
while (isdigit(number[i])){
i++;
}
printf("%d", i);
number[i] = 'b';
I have no compile errors, but when running program visual studio says
"Debug Assertion Fail".
Why is this not possible to do in C?
EDIT (whole code added):
#pragma warning(disable:4996) //disables crt warnings
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include<string.h>
double stof(char s[]);
int main(){
char string[] = "123.45e-10";
stof(string);
}
double stof(char s[]) {
bool isNegative = false;
bool eFound = false;
int i = 0;
int j = 0;
int k = 0;
char number[10];
char potention[11];
int dotPosition;
while (s[i] != '\0') {
if (isdigit(s[i]) && eFound == false) {
number[j++] = s[i];
}
else if (s[i] == '.') {
dotPosition = i;
}
else if (s[i] == 'e' || s[i] == 'E')
eFound = true;
else if (s[i] == '-')
isNegative = true;
else if (eFound== true && isdigit(s[i])){
potention[k++] = s[i];
}
i++;
}
i = 0;
while (isdigit(number[i])){
i++;
}
printf("%d", i);
number[i] = 'b';
const int charSize = dotPosition;
int potentionN = atoi(potention);
char beforeDecimal[sizeof(number)];
char addedNulls[20];
int g = 0;
if (isNegative == true) {
strncpy(beforeDecimal, number, dotPosition);
int addNull = potentionN - sizeof(beforeDecimal);
printf("%d", addNull);
while (g < addNull) {
addedNulls[g] = '0';
g++;
}
printf("%d", strlen(addedNulls));
}
return 0.0;
}

Why is this not possible to do in C?
Every computable answer can be found with a Turing-complete language. Your question is more like, where is the error in my code?
In C, it's very important to ensure you read & write only to defined memory: those locations covered by your variables. You're testing your input locations with
while (s[i] != '\0')
but nowhere do you ensure that you stay within the bounds of number and potention. Especially here:
i = 0;
while (isdigit(number[i])){
i++;
}
At no point do you write a nondigit to number. Why should that loop ever end?
The instant fix is to initialize number:
char number[10] = {};
That causes the compiler to initialize the array with any elements inside {}, and the rest of it with zeros. Since the initializer is empty, the whole array is filled with zeros.
That way, provided you don't fill number with digits, your while loop will terterminate. A belt-and-suspenders solution is make double-sure:
i = 0;
while (i < sizeof(number) && isdigit(number[i])) {
i++;
}
I haven't debugged your whole program; I haven't even compiled it. The run-time error you're seeing suggests you're writing to undefined memory. If you check the array bounds in each loop, you can avoid that particular problem and move on to the next one. ;-)

Related

char-Tables, Segmentation Error

I'm currently learning the C programming language, and I'm having some issues with it.
I'm getting Segmentation Error quite a lot when dealing with string (A.K.A char tables)
Here a simple algorithm just to delete the 'e' letter in the input string.
Example:
"hackers does exist" ->>> "hacks dos xist"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
char T[200];
int j,i,l,times=0;
printf("Entre THE TXT\n");
gets(T);
while (T[i] != '\0')
{
l++;
i++;
}
for (i=0;i<l;i++)
{
if ( T[i] == 'e')
{
times++;
}
}
l=l-times;
i=0;
j=0;
while (i<l)
{
if ( T[j] != 'e')
{
T[i]=T[j];
i++;
j++;
}
else j++;
}
for (i=0;i<l;i++)
{
printf("%c",T[i]);
}
return 0;
}
Can you please tell me what I did wrong?
PS: I have noticed that each time I do incrementation as j++ in this code I will get the Segmentation Error... I really don't understand why.
Initialize i, j, l variables. Since uninitialized local variables are indeterminate. Reading them prior to assigning a value results in undefined behavior.
You are accessing the i and l variable without initialization.
while (T[i] != '\0')
{
l++;
i++;
}
Initialize as below.
int j = 0, i = 0, l = 0, times = 0;
As kiran Biradar already answered you only missed to initialize your integers.
You have several options here. I'll write them from most common to most discouraged.
Most used form, verbose but easier to maintain later.
int i = 0;
int j = 0;
int l = 0;
int times = 0;
Short form 1:
int i = 0, j = 0, l = 0, times 0;
Short form 2:
int i, j, l, times;
i = j = l = times = 0;
I'd suggest you also to use the features of at least the C99 Standard and reduce the scope of your variables completely. (Yes I know it's possible with {}-Blocks but I kinda like for-loops, if you iterate completely over something.
Hence my suggestion for your code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h> // str(n)len
int main(void) // argv/argc is never used
{
char text[200];
printf("Entre THE TXT\n");
if (fgets(text, sizeof(text), stdin) == NULL) // fgets as gets is deprecated
exit(EXIT_FAILURE);
size_t len = strlen(text); // returns number of Characters excluding '\0'
if (len > 0 && text[len-1] == '\n') { // strip newline if present from fgets
text[len-1] = '\0';
}
unsigned int times = 0;
for (size_t i=0; i<len; i++) {
if (text[i] == 'e') {
times++;
}
}
// I'd prefer to use a `newlen` variable
len -= (size_t) times;
for (size_t j=0, i=0; i < len; j++) {
if (text[j] != 'e') {
text[i] = text[j];
i++;
}
}
text[len] = '\0'; // just for safety reasons terminate string properly
puts(text); // Use puts instead of calling printf several times.
return 0;
}
Further improvements:
Actually the times could be eliminated, as it's not really used to delete es.
So just remove the times block and all lines with it.

Most common character in a file in C

I'm doing my C programming course homework and I need to find a most common character in given file.
My testing with a testfile, emptyfile and other small amount text files works great (or at least I think so), but in the last long testfile something goes wrong and the error message is: "Should have returned 'e' (101) for file rfc791.txt. You returned 'b' (98)".
So what I'm asking that what might be wrong with my code, when suddenly the most common letter is not what is should be?
int most_common_character(char *filename) {
FILE *f;
if ((f = fopen(filename, "r")) == NULL) {
fprintf(stderr, "Not opened: %s\n", strerror(errno));
return -1;
}
char frequency[26];
int ch = fgetc(f);
if (ch == EOF) {
return 0;
}
for (ch = 0; ch < 26; ch++) {
frequency[ch] = 0;
}
while (1) {
ch = fgetc(f);
if (ch == EOF) {
break;
}
if ('a' <= ch && ch <= 'z') {
frequency[ch - 'a']++;
}
else if ('A' <= ch && ch <= 'Z') {
frequency[ch - 'A']++;
}
}
int maxCount = 0;
int maxChar = 0;
for (int i = 0; i <= 26; ++i) {
if (frequency[i] > maxCount) {
maxCount = frequency[i];
maxChar = i;
}
}
fclose(f);
return maxChar + 'a';
}
I would be very grateful if someone has any hints to fix my code :) I've tried to search the solution to this problem from many other related topics but nothing seems to work.
You should use < operator in the second for loop. Because of that when you are checking frequency[i] > maxCount, at frequency[26] it behaves undefined behaviour, meaning the value at that index may be less or higher than the compared value.
Your code do have some problems. However, they are so tiny so the code still works well with small tests.
int ch = fgetc(f); drop the first char in the file
for (int i = 0; i <= 26; ++i) break out of the array 's range (only from 0-->25)
Beside these small mistakes, your code is awesomely fine. Well done #thumbsup
Loop runs out-of-bounds. #Weather Vane
// for (int i = 0; i <= 26; ++i) {
for (int i = 0; i < 26; ++i) {
Code throws away result of the first character. #BLUEPIXY
int ch = fgetc(f);
if (ch == EOF) {
return 0;
}
// This value of ch is not subsequently used.
Other fixes as below
int most_common_character(char *filename) {
...
// Use a more generous count #Weather Vane
// char frequency[26];
// Consider there may be more than 26 different letters
// fgetc return EOF and value in the unsigned char range
int frequency[UCHAR_MAX + 1] = { 0 };
// Not needed as array was initialize above
// for (ch = 0; ch < 26; ch++) { frequency[ch] = 0; }
// BTW correct type declaration of int, avoided rookie mistake of using char
int ch;
// Codes use tolower(), islower() as that is the portable way to
// handle type-of-character detection
while ((ch = fgetc(f)) != EOF) {
frequency[tolower(ch)]++; // could add check to insure frequency[] does not overflow
}
int maxCount = 0;
int maxChar = -1;
for (int i = 0; i <= UCHAR_MAX; ++i) {
if (islower(i) && frequency[i] > maxCount) {
maxCount = frequency[i];
maxChar = i;
}
}
fclose(f);
return maxChar;
}

Having trouble looping over a function every time I read in a '\n' from an input file in C

For one of my programming classes we were supposed to write a program that could solve a sudoku puzzle using backtracking. While that was supposed to be the hard part, I'm embarrasingly stuck on parsing input.
The program is supposed to read in input in the form of:
2..5.4.3.1...9...8.........9...5...6.4.6.2.7.7...4...5.........4...8...1.5.2.3.4.
7.....4...2..7..8...3..8.799..5..3...6..2..9...1.97..6...3..9...3..4..6...9..1.35
....7..2.8.......6.1.2.5...9.54....8.........3....85.1...3.2.8.4.......9.7..6....
where the program reads in a line, and if it's a valid puzzle it solves it and prints the solution, then continues onto the next line, then the next until it eventually reaches EOF. Right now I have a function that reads in the puzzle using getchar(), and I got the idea from my instrctor to set a global variable that gets turned on when this function reaches EOF. Then in main have a while loop that essentially says
While(not done)
{
read puzzle
solve puzzle
}
Anyway, here's the actual code, I've only included the two functions that I'm trying to use to read input, I've confirmed everything about the actual sudoku solver works:
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int done = FALSE;
void readInPuzzle(int puzzle[9][9])
{
//puzzle [8][9] = '\0';
int i = 0;
int j = 0;
int c;
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
c = getchar();
if (c != '\n')
{
/*This converts the chars from getchar(); into easier to manage ints*/
if (c == '.') c = 48;
puzzle[i][j] = (c - '0');
}
if (c == EOF) done = TRUE;
}
}
}
void main()
{
int puzzle[9][9];
while (done == FALSE);
{
readInPuzzle(puzzle);
if (solvePuzzle(puzzle,0,0) == TRUE)
printPuzzle(puzzle);
}
}
When I run the program and give it the above input, it runs forever which I assume means the 'done' variable never gets set to 1. Am I way off base on how to use global variables? Is there a better way to have this program repeat itself every time it reads in a '\n' from input?
while (done == FALSE);
Here it stuck in that while statement only.
remove ;
while (done == FALSE)
{
readInPuzzle(puzzle);
if (solvePuzzle(puzzle,0,0) == TRUE)printPuzzle(puzzle);
}
sample to fix
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int readInPuzzle(int puzzle[9][9])
{
int i, j;
char c;
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
if(EOF == scanf(" %c", &c))
return FALSE;
if (c == '.') c = '0';
puzzle[i][j] = c - '0';
}
}
return TRUE;
}
int main(void)
{
int puzzle[9][9];
while (FALSE != readInPuzzle(puzzle))
{
if (solvePuzzle(puzzle,0,0) == TRUE)printPuzzle(puzzle);
}
return 0;
}
The following code corrects the logic for reading in the puzzle, handles certain input file format errors and corrects the problem with the 'while' statement in main()
Note: the stub functions solvePuzzle() and printPuzzle() are only added to make the posted code cleanly compile
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int done = FALSE;
int solvePuzzle(int puzzle[9][9], int row, int col)
{
puzzle = puzzle;
row = row;
col = col;
return TRUE;
}
void printPuzzle(int puzzle[9][9])
{
puzzle = puzzle;
}
void readInPuzzle(int puzzle[9][9])
{
//puzzle [8][9] = '\0';
int i = 0;
int j = 0;
int c;
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
c = getchar();
if( EOF == c )
{
if( i || j)
{ // then input file improperly formatted
printf("input file format incorrect, unexpected EOF at row=%d, col=%d\n", i, j );
}
done = TRUE;
return;
}
else if( '\n' == c )
{ // then input file improperly formatted
printf( "input file format incorrect, unexpected newline at row=%d col=%d\n", i, j );
done = TRUE;
return;
}
/*This converts the chars from getchar() into easier to manage ints*/
if (c == '.') c = '0';
puzzle[i][j] = (c - '0');
} // end for
} // end for
getchar(); // read newline (if any)
} // end function: readInPuzzle
int main( void )
{
int puzzle[9][9];
while ( !done )
{
readInPuzzle(puzzle);
if( done ) break;
if (solvePuzzle(puzzle,0,0) )
{
printPuzzle(puzzle);
}
}
return 0;
} // end function; main

How can I implement my anagram and palindrome functions to check the words input by a user?

I got some help earlier fixing up one of the functions I am using in this program, but now I'm at a loss of logic.
I have three purposes and two functions in this program. The first purpose is to print a sentence that the user inputs backwards. The second purpose is to check if any of the words are anagrams with another in the sentence. The third purpose is to check if any one word is a palindrome.
I successfully completed the first purpose. I can print sentences backwards. But now I am unsure of how I should implement my functions to check whether or not any words are anagrams or palindromes.
Here's the code;
/*
* Ch8pp14.c
*
* Created on: Oct 12, 2013
* Author: RivalDog
* Purpose: Reverse a sentence, check for anagrams and palindromes
*/
#include <stdio.h>
#include <ctype.h> //Included ctype for tolower / toupper functions
#define bool int
#define true 1
#define false 0
//Write boolean function that will check if a word is an anagram
bool check_anagram(char a[], char b[])
{
int first[26] = {0}, second[26] = {0}, c = 0;
// Convert arrays into all lower case letters
while(a[c])
{
a[c] = (tolower(a[c]));
c++;
}
c = 0;
while(b[c])
{
b[c] = (tolower(b[c]));
c++;
}
c = 0;
while (a[c] != 0)
{
first[a[c]-'a']++;
c++;
}
c = 0;
while (b[c] != 0)
{
second[b[c]-'a']++;
c++;
}
for (c = 0; c < 26; c++)
{
if (first[c] != second[c])
return false;
}
return true;
}
//Write boolean function that will check if a word is a palindrome
bool palindrome(char a[])
{
int c=0, j, k;
//Convert array into all lower case letters
while (a[c])
{
a[c] = (tolower(a[c]));
c++;
}
c = 0;
j = 0;
k = strlen(a) - 1;
while (j < k)
{
if(a[j++] != a[k--])
return false;
}
return true;
}
int main(void)
{
int i = 0, j = 0, k = 0;
char a[80], terminator;
//Prompt user to enter sentence, store it into an array
printf("Enter a sentence: ");
j = getchar();
while (i < 80)
{
a[i] = j;
++i;
j = getchar();
if (j == '!' || j == '.' || j == '?')
{
terminator = j;
break;
}
else if(j == '\n')
{
break;
}
}
while(a[k])
{
a[k] = (tolower(a[k]));
k++;
}
k = 0;
while(k < i)
{
printf("%c", a[k]);
k++;
}
printf("%c\n", terminator);
//Search backwards through the loop for the start of the last word
//print the word, and then repeat that process for the rest of the words
for(j = i; j >= 0; j--)
{
while(j > -1)
{
if (j == 0)
{
for(k=j;k<i;k++)
{
printf("%c", a[k]);
}
printf("%c", terminator);
break;
}
else if (a[j] != ' ')
--j;
else if (a[j] == ' ')
{
for(k=j+1;k<i;k++)
{
printf("%c", a[k]);
}
printf(" ");
break;
}
}
i = j;
}
//Check if the words are anagrams using previously written function
for( i = 0; i < 80; i++)
{
if (a[i] == ' ')
{
}
}
//Check if the words are palindromes using previously written function
return 0;
}
I was thinking that perhaps I could again search through the array for the words by checking if the element is a space, and if it is, store from where the search started to the space's index-1 in a new array, repeat that process for the entire sentence, and then call my functions on all of the arrays. The issue I am seeing is that I can't really predict how many words a user will input in a sentence... So how can I set up my code to where I can check for anagrams/palindromes?
Thank you everyone!
~RivalDog
Would be better,if you first optimize your code and make it readable by adding comments.Then you can divide the problem in smaller parts like
1.How to count words in a string?
2.How to check whether two words are anagrams?
3.How to check whether a word is palindrome or not?
And these smaller programs you could easily get by Googling. Then your job will be just to integrate these answers. Hope this helps.
To check anagram, no need to calculate number of words and comparing them one by one or whatever you are thinking.
Look at this code. In this code function read_word() is reading word/phrase input using an int array of 26 elements to keep track of how many times each letter has been seen instead of storing the letters itself. Another function equal_array() is to check whether both array a and b (in main) are equal (anagram) or not and return a Boolean value as a result.
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
void read_word(int counts[26]);
bool equal_array(int counts1[26],int counts2[26]);
int main()
{
int a[26] = {0}, b[26] = {0};
printf("Enter first word/phrase: ");
read_word(a);
printf("Enter second word/phrase: ");
read_word(b);
bool flag = equal_array(a,b);
printf("The words/phrase are ");
if(flag)
printf("anagrams");
else
printf("not anagrams");
return 0;
}
void read_word(int counts[26])
{
int ch;
while((ch = getchar()) != '\n')
if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')
counts[toupper(ch) - 'A']++;
}
bool equal_array(int counts1[26],int counts2[26])
{
int i = 0;
while(i < 26)
{
if(counts1[i] == counts2[i])
i++;
else
break;
}
return i == 26 ? true : false;
}

Need help creating a FindMaxOverlap function

I'm trying to create a function that, given two C strings, it spits back the number of consecutive character overlap between the two strings.
For example,
String 1: "Today is monday."
String 2: " is monday."
The overlap here would be " is monday.", which is 11 characters (it includes the space and '.').
If you need something more efficient, consider that a partial mismatch between Strings 1 and 2 means you can jump the length of the remainder of String 2 along String 1. This means you don't need to search the entirety of String 1.
Take a look at the Boyer-Moore algorithm. Though it is used for string searching, you could implement this algorithm for finding the maximum-length substring using String 2 as your pattern and String 1 as your target text.
There is probably a more efficient way to do this, but here's a simple approach:
#include <string.h>
int main() {
char s1[17] = "Today is monday.";
char s2[12] = " is monday.";
int max = 0;
int i_max = -1;
int j_max = -1;
int i = 0, j = 0, k=0;
int endl = 0, sl1, sl2;
char *ss1, *ss2;
for(i = 0; i < strlen(s1)-1; i++) {
ss1 = s1+i;
sl1 = strlen(ss1);
if(max >= sl1) {
break; // You found it.
}
for(j = 0; j < strlen(s2)-1; j++) {
ss2 = s2+j;
sl2 = strlen(ss2);
if(max >= sl2) {
break; // Can't find a bigger overlap.
}
endl = (sl1 > sl2)?sl2:sl1;
int n_char = 0;
for(k = 0; k < endl+1; k++) {
// printf("%s\t%s\n", ss1+k, ss2+k); // Uncomment if you want to see what it compares.
if(ss1[k] != ss2[k] || ss1[k] == '\0') {
n_char = k;
break;
}
}
if(n_char > max) {
max = n_char;
i_max = i;
j_max = j;
}
}
}
char nstr[max+1];
nstr[max] = '\0';
strncpy(nstr, s1+i_max, max);
printf("Maximum overlap is %d characters, substring: %s\n", max, nstr);
return 0;
}
Update: I have fixed the bugs. This definitely compiles. Here is the result: http://codepad.org/SINhmm7f
The problems were that endl was defined wrong and I wasn't checking for end-of-line conditions.
Hopefully the code speaks for itself.
Here is my solution, it will return the position of the overlap starting point, it's a bit complex, but that's how it's done in C:
#include <string.h>
int FindOverlap (const char * a, const char * b)
{
// iterators
char * u = a;
char * v = b;
char * c = 0; // overlap iterator
char overlapee = 'b';
if (strlen(a) < strlen(b)) overlapee = 'a';
if (overlapee == 'b')
{
while (*u != '\0')
{
v = b; // reset b iterator
c = u;
while (*v != '\0')
{
if (*c != *v) break;
c++;
v++;
}
if (*v == '\0') return (u-a); // return overlap starting point
}
}
else if (overlapee == 'a')
{
while (*v != '\0')
{
u = a; // reset b iterator
c = v;
while (*u != '\0')
{
if (*c != *u) break;
c++;
u++;
}
if (*v == '\0') return (v-b); // return overlap starting point
}
}
return (-1); // not found
}

Resources