Fill shape with asterisks - c

I wrote a program to fill in closed figures with asterisks.
For some reason it isn't accepting the sentinel value EOF Ctrl+D.
Why is this?
#include "usefunc.h"
#define height 100
#define width 100
void showRow(int numbers[], int size_numbers) {
int i;
printf("[ ");
for (i = 0; i < size_numbers-3; i++) {
printf("%c, ", numbers[i]);
}
printf("%c ]", numbers[size_numbers-3]);
printf("\n");
}
void showshape(int shape[][width], int lines, int max_buf) {
int i, j;
for (i = 0; i < lines; i++) {
for (j = 0; j < max_buf; j++) {
printf("%c", shape[i][j]);
}
printf("\n");
}
}
void fill(int row[][width], int rownum, int end) {
int i, c = 1, inside = 0;
for (i = 0; i < end; i++) {
if (row[rownum][i] == '*') {
c++;
}
if (!(c%2)) inside = 1;
else inside = 0;
if (inside) {
row[rownum][i] = '*';
}
}
}
int main () {
int shape[height][width], i = 0, j = 0, lines = 0;
int sentinel = 0;
int temp = 0;
while (sentinel != EOF) {
while ((temp = getchar()) != '\n') {
sentinel = temp;
shape[i][j] = temp;
j++;
}
i++;
lines++;
}
for (i = 0; i < lines; i++) {
fill(shape, i, width);
}
fill(shape, 0, j);
//for (i = 0; i < lines; i++)
showshape(shape, lines, j+2);
}
Edit 1
Just updated the code. It doesn't quite print the box. what's going on?
Edit 2
Another update. This time I'm copying the value of temp, however I get
Bus error
What am i doing wrong?

You want:
int temp;
EOF is an integer value, not a char.

while ((temp = getchar()) != '\n') {
shape`[i][j]` = temp;
j++;
}
I suspect this this never exits once EOF is reached. I mean, getchar probably continues to throw EOF at you and you ask "Not \n ? Okay, no need to stop".
Also, what #Neil Butterworth said in his answer is really sensible.

Related

Problem with counting elements in the list of names

I have made one program, where you enter a few characters (10 max). It makes you a list, count average length of surnames, tell about how much different names. But the problem is, when I enter the last number (10) - it sorts me it incorrectly (like 1, 10, 2, 3, 4, 5, 6, 7, 8, 9). Beneath I will present my code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct people {
char num[2];
char surname[20];
char name[10];
} peoples[10], c;
int main()
{
int i, j, k = 0, l = 0, m = 0, n = 0;
float s = 0;
char str[100];
system("chcp 1251 > nul");
for (i = 0, j = 0; i < 10; i++, j++)
{
printf("Enter number, surname, name %d of your human: ", i + 1);
gets(str);
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].num[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].surname[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != '\0')
{
peoples[j].name[k] = str[n];
}
else
break;
n++;
k++;
}
n = 0;
k = 0;
}
for (i = 0; i < 10; i++)
{
for (j = i + 1; j < 10; j++)
{
if (!strcmp(peoples[i].name, peoples[j].name))
m = 1;
}
if (m == 0)
l++;
m = 0;
s = s + strlen(peoples[i].surname);
}
for (i = 0; i < 9; i++)
for (j = 0; j < 9; j++)
if (strcmp(peoples[j].num, peoples[j+1].num) > 0)
{
c = peoples[j+1];
peoples[j+1] = peoples[j];
peoples[j] = c;
}
for (i = 0; i < 10; i++)
{
printf("%s ", peoples[i].num);
printf("%s ", peoples[i].name);
printf("%s ", peoples[i].surname);
printf("\n");
}
printf("\nYou have %d different names\n", l);
printf("Avarege lenght of surname is = %f\n", s / 10);
}
If you want to give numeric input, then use actual numeric data.
Change the num field to become an int instead of a single-character string:
struct people {
int num;
char surname[20];
char name[10];
};
Use fgets to read the line:
fgets(str, sizeof str, stdin);
[Error checking left as exercise for reader]
Then use e.g. sscanf for parse your string:
sscanf(str, "%d %s %s", &peoples[j].num, &peoples[j].name, &peoples[j].name);
[Error checking left as exercise for reader]
And finally, instead of doing your own sorting use the standard qsort function:
qsort(peoples, 10, sizeof(struct people), &compare_people_num);
With the comparison function being something like this:
int compare_people_num(const void *a, const void *b)
{
const struct people *p1 = a;
const struct people *p2 = b:
return p1->num - p2->num; // Change order to reverse sort
}
Using sscanf and qsort will make your code much simpler and easier to understand.

String manipulation (variable output with the same input)

Maybe some property is passing unnoticed to me, but when 'i' is 1 it just freeze. When i input whatever string, 'j' variable goes to 700 or 2000 in different executions. The code goal is to output repetitive letters if you input "cheese" the output should be "eee". What am i doing wrong?
#include <stdio.h>
char * repeticoes(char *s) {
int index = 0;
for (int i = 0;( s[i] != '\0'); i++) //problem starts when i is > 0
{
for (int j = 0; ( s[j] != '\0'); j++)
{
if (s[i] == s[j])
{
printf("%c == %c\ni %d j %d\n", s[i], s[j],i,j);
s[index++] = s[i];
}
else
{
printf("not happening %c != %c\ni %d j %d\n", s[i],s[j],i,j);
}
}
}
s[++index] = '\0';
return s;
}
main() {
char input[21];
printf("str 1\n");
fgets(input, 20, stdin);
repeticoes(input);
printf("duplicated letters %s\n", input);
}
You need to start the inner loop at the next character after the one being processed in the outer loop, otherwise you'll process the same pair of characters twice, as well as testing a character against itself when i == j.
You should also break out of the inner loop as soon as you find a match. You'll find later matches in a future iteration of the outer loop. Otherwise you'll process the same pair twice again.
And you shouldn't increment index before assigning the null character after the loop. It was already incremented when adding the repetition.
#include <stdio.h>
char * repeticoes(char *s) {
int index = 0;
for (int i = 0;( s[i] != '\0'); i++) //problem starts when i is > 0
{
for (int j = i+1; ( s[j] != '\0'); j++)
{
if (s[i] == s[j])
{
printf("%c == %c\ni %d j %d\n", s[i], s[j],i,j);
s[index++] = s[i];
break;
}
else
{
printf("not happening %c != %c\ni %d j %d\n", s[i],s[j],i,j);
}
}
}
s[index] = '\0';
return s;
}
int main() {
char input[21];
printf("str 1\n");
fgets(input, 20, stdin);
repeticoes(input);
printf("duplicated letters %s\n", input);
}
With an array of letters to count and an array of counts. Once the letters have been counted, loop through the input again and set the letters that have a count greater than one.
#include <stdio.h>
void repeticoes ( char *s) {
char tocount[] = "abcdefghijklmnopqrstuvwxyz";
size_t len = sizeof tocount;
size_t index = 0;
int count[len];
for (int j = 0; j < len; j++) {
count[j] = 0;
}
for (int i = 0;( s[i] != '\0'); i++) {
for (int j = 0; j < len; j++) {
if ( s[i] == tocount[j]) {
count[j]++;
}
}
}
for (int i = 0;( s[i] != '\0'); i++) {
for (int j = 0; j < len; j++) {
if ( s[i] == tocount[j] && 1 < count[j]) {
s[index] = s[i];
index++;
}
}
}
s[index] = '\0';
}
int main ( void) {
char input[21];
printf("str 1\n");
fgets(input, 20, stdin);
repeticoes(input);
printf("duplicated letters %s\n", input);
return 0;
}

Numbers in char array printing as random characters

So I'm writing a somewhat simple C program that is supposed to take a string of characters separated by semicolons as input. The program is then supposed to sort the strings by length and print them to the console.
Ex: abc;12;def;1234
The issue I'm having is that any numbers that are entered end up being printed as random symbols and I'm not sure why. I'm taking in input in this function:
void get_strings(char** c)
{
while (scanf("%[^;]s", c[numStrings]) != EOF)
{
getchar();
numStrings += 1;
}
}
Since scanf is looking for strings, if numbers are entered, are they stored as the 'character form' of those numbers, or should I be casting somehow?
Here's the rest of the code:
int numStrings = 0;
void sort_strings(char** c)
{
for (int i = 0; i < numStrings; i++)
{
for (int j = 0; j < numStrings - i; j++)
{
if (strlen(c[j]) > strlen(c[j + 1]))
{
char temp[1000];
strcpy(c[j], temp);
strcpy(c[j + 1], c[j]);
strcpy(temp, c[j + 1]);
}
}
}
}
void show_strings(char** c)
{
for (int i = 0; i < numStrings; i++)
{
if (printf("%s\n", c[i]) != EOF) break;
}
}
int main()
{
char wordLen[100][1000];
char* word2[100];
for (int i = 0; i < 100; i++)
{
word2[i] = wordLen[i];
}
char** words = word2;
get_strings(words);
sort_strings(words);
show_strings(words);
return 0;
}
The parsing code is incorrect:
void get_strings(char **c) {
while (scanf("%[^;]s", c[numStrings]) != EOF) {
getchar();
numStrings += 1;
}
}
the scanf() format contains an extra s that does not match the input.
the return value of scanf() should be compared to 1 to ensure successful conversion. Conversion failure produces EOF only at end of file, otherwise it produces 0 and the contents of c[numStrings] will be indeterminate.
conversion stops at the first character ;, this character stays in the input stream, but it is read by getchar(), yet if there is an empty field, the corresponding conversion would fail and the contents of the array would be indeterminate.
you should not use a global variable for the number of strings read. You should instead return this number.
The sorting code is incorrect too:
the inner loop runs one index too far: j + 1 must be less than numStrings for all runs.
the arguments to strcpy are passed in the wrong order.
strcpy should not be used at all, you should just swap the pointers.
show_strings() always stops after the first line as printf will return the number of characters printed.
You can fix the reading loop this way:
#include <stdio.h>
#include <string.h>
int get_strings(char **c, int maxStrings) {
int numStrings = 0;
while (numStrings < maxStrings) {
switch (scanf("%999[^;]", c[numStrings])) {
case 1:
getchar();
numStrings += 1;
break;
case 0:
if (getchar() == ';') {
c[numStrings] = '\0';
numStrings += 1;
}
break;
case EOF:
return numStrings;
}
}
}
void sort_strings(char **c, int count) {
for (int i = 0; i < count; i++) {
for (int j = 0; j < count - i - 1; j++) {
if (strlen(c[j]) > strlen(c[j + 1])) {
char *temp = c[j];
c[j] = c[j + 1];
c[j + 1] = temp;
}
}
}
}
void show_strings(char **c, int count) {
for (int i = 0; i < count; i++) {
printf("%s\n", c[i]);
}
}
int main(void) {
char words[1000][100];
char *wordPtrs[100];
int numStrings;
for (int i = 0; i < 100; i++) {
wordPtrs[i] = words[i];
}
numStrings = get_strings(wordPtrs, 100);
sort_strings(wordPtrs, numStrings);
show_strings(wordPtrs, numStrings);
return 0;
}

trying to use strcmp in if function for counting anagrams in a sentence

hii guys i need a serious help
i m trying to write a code for finding anagrams in input sentence
but when the if function is getting strcmp it stops and its not accepting the condition. any body know why is that happening
Basically my code supposed to do two things one is taking a sentence from the user and making the words appear in the Backwoods order two Its need to take the whole sentence and look for anagrams ( anagram means that there is the same letters but in a different order for example this and shit are anagrams) thank you very much for your help :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int index_for_word_start, words_num = 1,amount_of_letters;
int i, j, k;
char inpot_Sentence[1001], temp_letters;
char **words,**sorting_words;
int counter = 0,counter_max_for_anegram=0;
printf_s("Please enter the sentence, and then press Enter:\n");
gets(inpot_Sentence);
/////////////////////////////makeing the sentence backwards///////////////////////
for (i = 0; inpot_Sentence[i] != '\0'; i++) //loop for counting how many words(it will be use to know how many pointer we need)
{
if (inpot_Sentence[i] == ' ')
{
words_num++;
}
}
words = (char **)malloc(sizeof(char *)*words_num); //malloc for pointers that point on the pointer of the word
index_for_word_start = 0;
for (j = 0; j<words_num; j++)
{
for (i = index_for_word_start; inpot_Sentence[i] != ' '; i++)
{
if (!inpot_Sentence[i]) //if the user didnt put any word(break)
{
break;
}
}
words[j] = (char*)malloc(sizeof(char)*(i - index_for_word_start + 1)); //malloc of pointers that point on each word
strncpy_s(words[j], i - index_for_word_start+1, &inpot_Sentence[index_for_word_start], i - index_for_word_start); //copy the words from inpot sentence to array
words[j][i - index_for_word_start] = 0; //puts '\0' after the word copy ends
index_for_word_start = i + 1;
}
printf_s("\nThe reverse sentence is:\n");
for (i = words_num - 1; i >= 0; i--) //print the words in backwards Sequence
{
printf("%s ", words[i]);
}
putchar('\n');
i = 0;
/////////////////////anegrams check///////////////////////
for (j = 0; j < words_num; j++) //loops that Arrange the array by haski value
{
amount_of_letters = strlen(words[j]);
for ( i = 0; i < amount_of_letters; i++)
{
for (k = 0; k < amount_of_letters; k++)
{
if (words[j][i]<words[j][k])
{
temp_letters = words[j][i];
words[j][i] = words[j][k];
words[j][k] = temp_letters;
}
}
}
printf_s("this is words %s\n", words[j]);
}i = 0;
for ( j = 0; j < words_num-1; j++)
{
for ( i = 0; i < words_num-1; i++)
{
if (!strcmp(words[j],words[i]) && (i!=j) && (strcmp(words[j],"\0")))
{
counter++;
words[i] = 0;
}
else
{
break;
}
}
if (counter>counter_max_for_anegram)
{
counter_max_for_anegram = counter;
}
counter = 0;
}
printf_s("%d\n", counter_max_for_anegram);
for ( j = 0; j < words_num; j++)
{
free(words[j]);
}
free(words);
}
#include <stdio.h>
#include <string.h>
int check_anagram(char[],char[]);
int main()
{
char a[100],b[100];
int flag;
puts("Enter the first string");
fgets(a,100,stdin);
a[strcspn(a, "\r\n")] = '\0';
puts("Enter the second string");
fgets(b,100,stdin);
b[strcspn(b, "\r\n")] = '\0';
flag=check_anagram(a,b);
if(flag)
printf("%s and %s are anagrams",a,b);
else
printf("%s and %s are not anagrams",a,b);
}
int check_anagram(char a[], char b[])
{
int first[26]={0},second[26]={0},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 0;
}
return 1;
}

C-printing a histogram

This is a question from K&R:-
Write a program to print a histogram of the lengths of words in its input.It is easy to draw the histogram with bars horizontal; but a vertical orientation is more challenging.
I am not supposed to use any library functions because this is only a tutorial introduction!
I have written the following program to do so but it have some bugs:-
1)If there is more than one white-space character between words, the program doesn't work as expected.
2)How do I know the maximum value of 'k' I mean how to know how many words are there in the input?
Here is the code:-
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define MAX_WORDS 100
int main(void)
{
int c, i=0, k=1, ch[MAX_WORDS] = {0};
printf("enter the words:-\n");
do
{
while((c=getchar())!=EOF)
{
if(c=='\n' || c==' ' || c=='\t')
break;
else
ch[i]++;
}
i++;
}
while(i<MAX_WORDS);
do
{
printf("%3d|",k);
for(int j=1;j<=ch[k];j++)
printf("%c",'*');
printf("\n");
k++;
}
while(k<10);
}
This program will work fine even if there are more than one newline characters in between the two words and numWords will give you the numbers of words.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int ch, cha[100] = {0}, k = 1;
int numWords = 0;
int numLetters = 0;
bool prevWasANewline = true; //Newlines at beginning are ignored
printf("Enter the words:-\n");
while ((ch = getchar()) != EOF && ch != '\n')
{
if (ch == ' ' || ch == '\t')
prevWasANewline = true; //Newlines at the end are ignored
else
{
if (prevWasANewline) //Extra nelines between two words ignored
{
numWords++;
numLetters = 0;
}
prevWasANewline = false;
cha[numWords] = ++numLetters;
}
}
do
{
printf("%3d|",k);
for(int j=0;j<cha[k];j++)
printf("%c",'*');
printf("\n");
k++;
} while(k <= numWords);
return 0;
}
Its kind of an old thread, but i had the same problem. The code above works like charm, but its kind of an overkill for the knowledge we have with K&R in the first 20 pages.
I had no idea what they meant by histogram printing and that code helped me with that.
Anyway i wrote a code myself with the knowledge i gained through the book, i hope it will be helpful to someone.
Forgive me if its a bit messy, i am just a beginner myself :D
#include <stdio.h>
#define YES 1
#define NO 0
int main(void)
{
int wnumb [100];
int i, inword, c, n, k;
n = (-1);
for (i = 0; i <=100; ++i) {
wnumb [i] = 0;
}
inword = NO;
while ((c = getchar()) != EOF) {
if ( c == ' ' || c == '\n' || c == '\t' ) {
inword = NO;
}
else if (inword == NO) {
++n;
++wnumb [n];
inword = YES;
}
else {
++wnumb [n];
}
}
for (i = 0; i <= 100; ++i) {
if (wnumb [i] > 0) {
printf ("\n%3d. | ", (i+1));
for (k = 1; k <= wnumb[i]; ++k) {
printf("*");
}
}
}
printf("\n");
}
Here is example of simple Histogram(Vertically)
#include <stdio.h>
int main()
{
int c, i, j, max;
int ndigit[10];
for (i = 0; i < 10; i++)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
max = ndigit[0];
for (i = 1; i < 10; ++i) /* for Y-axis */
if (max < ndigit[i])
max = ndigit[i];
printf("--------------------------------------------------\n");
for (i = max; i > 0; --i) {
printf("%.3d|", i);
for (j = 0; j < 10; ++j)
(ndigit[j] >= i) ? printf(" X ") : printf(" ");
printf("\n");
}
printf(" ");
for (i = 0; i < 10; ++i) /* for X-axis */
printf("%3d", i);
printf("\n--------------------------------------------------\n");
return 0;
}

Resources