Summing triplets in C - c

Okay so I have a file with a bunch of digits
002003005\n
001001\n
and I want to sum all the digits by three so the first lines sum would be 10 and the second line would be 2. Right now I'm not sure whats wrong with my control flow
#define MAXLINE 1000
int counter = 0;
int inputLine[MAXLINE] = {0};
int main(void)
{
int sum = 0;
int i = 0;
int ii = 0;
char c;
while ((c = getchar()) != EOF)
{
if (c == '\n')
{
for (ii = 0; ii < counter; ii = ii + 3)
{
sum = sum + ((inputLine[ii] - '0') * 100) + ((inputLine[ii+1] - '0') * 10) + ((inputLine[ii+2] - '0') * 1);
}
printf("%d\n", sum);
sum = 0;
counter = 0;
}
inputLine[i] = c;
i++;
counter++;
}
return 0;
}

You're not resetting i when you reach the end of a line.
Insert:
i = 0;
After the counter = 0 line.
You also need to include this block:
inputLine[i] = c;
i++;
counter++;
Within an else, since it shouldn't happen for the carriage return at the end of each line.
Once you've done that, you'll (hopefully) notice that i and counter will always contain the same value on each pass through the loop, so there's no need for them both to exist.

If your char type is unsigned by default then your end condition is not good
char c;
while ((c = getchar()) != EOF)
You should declare c as int, as EOF cannot be represented in the value range of 0..255. EOF is by definition a negative integer of type int used to indicate end-of-file conditions.

Related

Program to count length of each word in string in C

I'm writting a program to count the length of each word in array of characters. I was wondering if You guys could help me, because I'm struggling with it for at least two hours for now and i don't know how to do it properly.
It should go like that:
(number of letters) - (number of words with this many letters)
2 - 1
3 - 4
5 - 1
etc.
char tab[1000];
int k = 0, x = 0;
printf("Enter text: ");
fgets(tab, 1000, stdin);
for (int i = 2; i < (int)strlen(tab); i++)
{
for (int j = 0; j < (int)strlen(tab); j++)
{
if (tab[j] == '\0' || tab[j]=='\n')
break;
if (tab[j] == ' ')
k = 0;
else k++;
if (k == i)
{
x++;
k = 0;
}
}
if (x != 0)
{
printf("%d - %d\n", i, x);
x = 0;
k = 0;
}
}
return 0;
By using two for loops, you're doing len**2 character scans. (e.g.) For a buffer of length 1000, instead of 1000 character comparisons, you're doing 1,000,000 comparisons.
This can be done in a single for loop if we use a word length histogram array.
The basic algorithm is the same as your inner loop.
When we have a non-space character, we increment a current length value. When we see a space, we increment the histogram cell (indexed by the length value) by 1. We then set the length value to 0.
Here's some code that works:
#include <stdio.h>
int
main(void)
{
int hist[100] = { 0 };
char buf[1000];
char *bp;
int chr;
int curlen = 0;
printf("Enter text: ");
fflush(stdout);
fgets(buf,sizeof(buf),stdin);
bp = buf;
for (chr = *bp++; chr != 0; chr = *bp++) {
if (chr == '\n')
break;
// end of word -- increment the histogram cell
if (chr == ' ') {
hist[curlen] += 1;
curlen = 0;
}
// got an alpha char -- increment the length of the word
else
curlen += 1;
}
// catch the final word on the line
hist[curlen] += 1;
for (curlen = 1; curlen < sizeof(hist) / sizeof(hist[0]); ++curlen) {
int count = hist[curlen];
if (count > 0)
printf("%d - %d\n",curlen,count);
}
return 0;
}
UPDATE:
and i don't really understand pointers. Is there any simpler method to do this?
Pointers are a very important [essential] tool in the C arsenal, so I hope you get to them soon.
However, it is easy enough to convert the for loop (Removing the char *bp; and bp = buf;):
Change:
for (chr = *bp++; chr != 0; chr = *bp++) {
Into:
for (int bufidx = 0; ; ++bufidx) {
chr = buf[bufidx];
if (chr == 0)
break;
The rest of the for loop remains the same.
Here's another loop [but, without optimization by the compiler] double fetches the char:
for (int bufidx = 0; buf[bufidx] != 0; ++bufidx) {
chr = buf[bufidx];
Here is a single line version. Note this is not recommended practice because of the embedded assignment of chr inside the loop condition clause, but is for illustration purposes:
for (int bufidx = 0; (chr = buf[bufidx]) != 0; ++bufidx) {

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;
}

C - Read in float value using getchar and print out float using printf

I'm extremely lost and confused.
I have to read in a float integer like 3.432 using getchar. Then, I have to print it out again as a float with a precision of 4 decimal places using printf. So 3.432 --> 3.4320 and .450 --> .4500, and 453 --> 453.0000.
I've been using getchar() and I understand that, but trying to reconvert the value as a float is where I'm just extremely lost.
float num = 0.0;
char ch;
while((ch = getchar()) != '\n'){
num = ch - '0';
printf("%.4f", num);
}
I know why that is wrong and what it outputs but that's what I have so far
EDIT: I can only use getchar to read the float values
Not tested (no time). Hope it helps.
#include <stdio.h>
int main(void)
{
float num = 0.0;
float i = 1.0;
char ch;
printf("Enter a float number: ");
while((ch = getchar()) != '\n')
{
if (ch == '.')
{
i = 0.1;
}
else if ((ch>= '0') && (ch <='9'))
{
if (i==1)
{
num *= 10;
num += ch - '0';
}
else
{
num += (ch - '0') * i;
i /= 10;
}
}
}
printf("%.4f\n", num);
return 0;
}
Ok, so you should first specify what you want - as usual keep away from the keybord until you exactly know what you want to build:
read until end of file or first new line
skip initial blank characters (optional but not expensive)
ignore trailing blank character (optional but not expensive)
reject any non blank after first trailing blank
reject any character other than blanks, digits and dot
process the integer part (until first dot) but multiplying current value by 10 and adding character code minus char '0'
ensure at most one dot
process the decimal part by adding char - '0' multiplied by 0.1 power decimal position
Once that has been stated coding is simple and could be:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void error(int pos, char c) {
fprintf(stderr, "Unwanted character %c at %d\n", c, pos);
exit(1);
}
int main() {
double f = 0.;
int c;
bool initial = 1, final=0;
int pos = 0;
double decimal = 0;
while (((c = getchar()) != EOF) && (c != '\n')) {
pos += 1;
if (isspace(c)) { // accept spaces before and after the number
if (initial || final) continue;
else {
final = 1;
continue;
}
}
else if (final) { // do not accept anything after a space after the number
error(pos, c);
}
initial = 0; // at least one non blank char
if (c == '.') {
if (decimal) { // accept only one decimal dot
error(pos, c);
}
else decimal = 1;
}
else if (! isdigit(c)) { // only digits
error(pos, c);
}
else if (decimal == 0) {
f = f * 10 + c - '0'; // integer part
}
else {
decimal *= .1; // fractional part
f += (c - '0') * decimal;
}
}
printf("%.4f\n", f);
return 0;
}
As a bonus I showed you how to process error conditions
It would be simpler if you first write a function reading integer.
Then you can think about writing a function reading the decimal part and combine the result.
Also, you need to accumulate the read information. At the moment you are overwriting previously read digit with a new one.
Another possibility using only stdio in solving the task could be a simple two-step process:
declaring and reading the input into a character array, using some more or less sophisticated fool-proofing
"parsing" the array members on the left and right hand side of the decimal point and multiplying the ('0' offset subtracted value) by the corresponding power of 10.
_
#include <stdio.h>
int main(void)
{
float power_of_ten, num = 0.;
char c, ch[32];
int j, i = 0;
int point_pos = -1; //initialize decimal point position 'offscale'
while(((c = getchar()) != EOF) && (c != '\n')) //simple fool-proof check
if(((c >= '0')&&(c <= '9')) || (( c == '.')&&(point_pos == -1))){
ch[i] = c;
if(ch[i] == '.')
point_pos = i;
i++;
}
ch[++i] = '\0'; //length of the array
//parsing the array
if(point_pos >= 0){ //to the right of decimal point
power_of_ten = .1;
for(j = point_pos + 1; j < i-1; j++){
num += (float)(ch[j] - '0')*power_of_ten;
power_of_ten *= .1;
}
}
power_of_ten = 1.; //to the left of decimal point
if(point_pos == -1)point_pos = i-1;
for(j = point_pos - 1; j >= 0 ; j --){
num += (float)(ch[j] - '0')*power_of_ten;
power_of_ten *= 10;
}
printf("%.4f\n", num);
return 0;
}
Hope this helps!!
#include<stdio.h>
#include<string.h>
#include<math.h>
int findNumOfDigits(int num);
int main(void)
{
char c;
float f, mod, fractional;
char *buff = malloc(10), *fptr;
char *str = buff;
int digits;
printf("Enter any number\n");
c = getchar();
while(c!='\n')
{
*buff = c;
buff = buff+1;
c = getchar();
}
*buff = '\0';
mod = atoi(str);
fptr = strstr(str, ".");
if(fptr!=NULL)
fptr++;
fractional = atoi(fptr);
digits = findNumOfDigits(fractional);
f = (mod + (fractional/pow(10,digits)));
printf("Number converted to float = %f", f);
return 0;
}
int findNumOfDigits(int num)
{
int i;
for(i = 1; num >= 10; i++)
{
num = num/10;
}
return i;
}

using array to store big numbers

i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}
Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.

Using getchar() to store a value to compare with an integer

i'm trying to count how many times a user inputs a certain digit and assign total number of instances to a location in a 10 row array (0-9). For instance if the user inputs 888, it will assign 3 to location arr1[8].
#include <stdio.h>
#include <stdlib.h>
int main(void){
int arr1[10] = {0};
int c;
while ((c = getchar()) != '\n'){
for (int i = 0; i <= 9; i++){
if (c == i) // This isn't doing what I want it to do
arr1[i] += 1;
}
}
for (int i = 0; i <= 9; i++)
printf ("%c ", arr1[i]);
}
The trouble seems to be the line that i've added to comment above. The line if (c == i) is intended to compare a user inputed digit (as it's entered by the user, not the ASCII value) and compare it with i.
So how can I compare c and i as the same type? I've tried changing the type of getchar() to char, signed int, unsigned int but it doesn't seem to make any difference.
You have to substract '0'.
You are printing char using %c for count.
You are incrementing by the count by i in the loop rather you wanted to increment by 1 for each character.
Corrected code:
int main(void){
int arr1[10] = {0};
int c;
while ((c = getchar()) != '\n'){
for (int i = 0; i <= 9; i++){
if (c - '0' == i)
arr1[i] += 1;
}
}
for (int i = 0; i <= 9; i++)
printf ("%d ", arr1[i]);
}
You have to perform the following operation to convert the ASCII value to corresponding integer,
c=c-48;
Inside your for loop,
arr1[i] += i;
should be,
arr1[i] += 1;
#include <stdio.h>
int main(void){
int arr1[10] = {0};
char table[] = "0123456789";
int c;
while ((c = getchar()) != '\n'){
for (int i = 0; i <= 9; i++){
if (c == table[i])//or table[i] --> "0123456789"[i]
arr1[i] += 1;
}
}
for (int i = 0; i <= 9; i++)
printf ("%d ", arr1[i]);
}
getchar will return ASCII code for c, not the numerical value. Simplest solutions exploits the fact that numbers 0-9 are sequential in the ASCII table, just subtract the offset:
int number = getchar() - '0';
if (number == i) {
//....
}
This is just an example, always check the return value of getchar for error codes.
Finally, in this line:
printf ("%c ", arr1[i]);
Use %d as format specifier instead: you want to print a number, not a character.

Resources