I tried to write a program that prints a diamond with mirrored letters like the following shape:
a
aba
abcba
abcdcba
abcdedcba
abcdefedcba
abcdedcba
abcdcba
abcba
aba
a
here is what I have done already:
#include <stdio.h>
int main()
{
int n, c, k,f=0, space = 1;
char ch='a';
printf("enter the size of diamond\n");
scanf("%d", &n);
space = n - 1;
for (k = 1; k <= n; k++)
{
for (c = 1; c <= space; c++)
printf(" ");
space--;
for (c = 1; c <= 2*k-1; c++)
if (c <= f)
printf("%c", ch);
ch++;
if (c>f)
ch--;
printf("%c", ch);
printf("\n");
}
space = 1;
for (k = 1; k <= n - 1; k++)
{
for (c = 1; c <= space; c++)
printf(" ");
space++;
for (c = 1 ; c <= 2*(n-k)-1; c++)
printf("a");
printf("\n");
}
return 0;
}
But apparently there is some error in this code, can any one help me detect it?
If you replace this
for (c = 1 ; c <= 2*(n-k)-1; c++)
printf("a");
with this
for (c = 0 ; c < 2*(n-k)-1; c++) // note the different conditions
printf("%c", 'a' + c); // print char instead of string
you should get each line of the correct length but with increasing chars like
abcde
but it doesn't decrease from the midpoint. I leave that to you!
It would be easier to separate tasks to function. So the function to calculate the character to be printed based on the position and the line length would be:
int getCharAtPos(int pos, int len)
{
if (pos > len / 2)
{
return 'a' + len - pos;
}
else
{
return 'a' + pos - 1;
}
}
And then instead of printf("a") you would use
for (c = 1; c <= 2*k-1; c++)
printf("%c", getCharAtPos(c, 2*k-1));
.....
for (c = 1 ; c <= 2*(n-k)-1; c++)
printf("%c", getCharAtPos(c, 2*(n-k)-1));
There is a second solution of the problem.
You can use recursion.
I wrote an example for your task.
//--------------
// Recursive Out one Simbol
void DamSimRec(char chOut ,int scnt)
{
printf("%c", chOut);
if (scnt > 1)
{
DamSimRec(chOut + 1, scnt - 1);
printf("%c", chOut);
}
}// Print Space
//--------------
void SpaceOut(int pSizeSpace)
{
int a_c;
for (a_c = 0; a_c < pSizeSpace; a_c++)
printf(" ");
}
//--------------
// Recursive Print One String Krylov E.A.
void DamRec(int space, int sout)
{
SpaceOut(space);//space;
DamSimRec('a', sout);//Simbols
printf("\n");
if (space > 0)
DamRec(space-1, sout+1);
if (sout > 1)
SpaceOut(space + 1);
DamSimRec('a', sout - 1);
}
printf("\n");
}
main()
{
int aSize;
printf("enter the size of diamond\n");
scanf_s("%d", &aSize);
DamRec(aSize , 1);
}
...So, You can use that, but remember about stack.
int n, c, k, space;
printf("enter the size of diamond\n");
scanf("%d", &n);
char s[n+2];
s[0] = 'a';s[1] = '\0';
for(c = 0; c < n; ++c){
space = n - c -1;
printf("%*s", space, "");
k = printf("%s", s) - 1;
while(--k >=0)
putchar(s[k]);
puts("");
s[c+1] = s[c] + 1;
s[c+2] = '\0';
}
for(c = 1; c < n; ++c){
space = c;
printf("%*s", space, "");
k = printf("%.*s", n - c, s) - 1;
while(--k >=0)
putchar(s[k]);
puts("");
}
#include <stdio.h>
void print(char from, char to){
putchar(from);
if(from < to){
print(from+1, to);
putchar(from);
}
}
int main(void){
int c = 0, n, k = 1;
printf("enter the size of diamond\n");
scanf("%d", &n);
do{
printf("%*s", n - c -1, "");
print('a', 'a' + c);
puts("");
if(c + 1 == n)
k = -k;
c += k;
}while(c>=0);
return 0;
}
Related
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.
Code:
#include <stdio.h>
#include <string.h>
void check(char *s, char *b)
{
int l, l1;
l = strlen(s);
l1 = strlen(b);
int i = 0, j = 0, count = 0;
while (i < l & j < l1)
{
if (s[i] == b[j])
{
j = j + 1;
count++;
}
i = i + 1;
}
if (count == l1)
{
printf("POSITIVE");
}
else
{
printf("NEGATIVE");
}
}
int main()
{
char s[100], b[100];
scanf("%s", s);
int a, i;
scanf("%d", &a);
for (i = 0; i < a; i++)
{
scanf("%d", &b[i]);
check(s, b);
}
}
Input:
CORONAVIRUS
3
abdce
ravus
onarous
Expected output:
NEGATIVE
POSITIVE
NEGATIVE
My output is like:
NEGATIVENEGATIVENEGATIVE
This is wrong.
scanf("%d", &b[i]);
You have asked the compiler to expect a int input by writing %d. However, you are entering a string. Change it to:
scanf("%s", b);
Also, you are making comparisons between lowercase and uppercase. In that case, change the lowercase character to uppercase character using the function toupper(). Or alternatively use tolower() to change it to lower case.
Your comparison should look like this to make case insensitive character comparison.
if (s[i] == b[j])
Change it to:
if (s[i] == b[j] || s[i]==toupper(b[j]) || tolower(s[i])==b[j])
Your complete code may look like this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void check(char *s, char *b)
{
int l, l1;
l = strlen(s);
l1 = strlen(b);
int i = 0, j = 0, count = 0;
while (i < l & j < l1)
{
if (s[i] == b[j] || s[i]==toupper(b[j]) || tolower(s[i])==b[j])
{
j = j + 1;
count++;
}
i = i + 1;
}
if (count == l1)
{
printf("POSITIVE\n");
}
else
{
printf("NEGATIVE\n");
}
}
int main()
{
char s[100], b[100];
scanf("%s", s);
int a, i;
scanf("%d", &a);
for (i = 0; i < a; i++)
{
scanf("%s", b);
check(s, b);
}
return 0;
}
"Exercise 1-23. Write a program to remove all comments from a C program.
Don't forget to handle quoted strings and character constants
properly. C comments do not nest." K&R pg.34
Basically, I have two questions:
1)I'm completely new coding and I wanted to know if I'm at least thinking the problem the right way.
2)The code was built to ignore // till \n or /* till */. But whit the /* comment it always leaves one /.
Input: abc/*comment*/123
Output: abc/123
Input: abc/*123
Output: abc/
#include <stdio.h>
char s[1000]; //Principal array
int countS; //Number of char in array
int deletSingleLineComments(void);
int deletMultiLineComments(void);
int main(void){
int c;
while((c=getchar())!=EOF){
s[countS]=c;
++countS;
}
deletMultiLineComments(); //Function 1
deletSingleLineComments(); //Function 2
printf("\ns[]=\n%s\n\ncountS[]=%d\n",s,countS);
}
//Functions 1
int deletMultiLineComments(void){
char t[1000];
int i=0;
int inComment=0;
int diff=0;
int a,b,c;
while(i<=countS){
t[i]=s[i];
++i;
}
i=0;
while(i<=countS){
if(t[i]=='/' && t[i+1]=='*'){
inComment=1;
}
if(inComment==1){
++diff; //to equilibrate the number
}
if(inComment==0){
s[i-diff]=t[i];
}
if(t[i]=='*' && t[i+1]=='/'){
inComment=0;
}
++i;
}
s[i-diff+1]='\0';
countS=i-diff;
printf("\nt[]=\n%s\n",t);
}
//Function 2
int deletSingleLineComments(void){
int i=0;
char t[1000];
int inComment=0;
int diff=0;
while(i<=countS){
t[i]=s[i];
++i;
}
i=0;
while(i<=countS){
if(t[i] == '/' && t[i+1] == '/'){
inComment=1;
}
if(t[i]=='\n'){
inComment=0;
}
if(inComment==1){
++diff;
}
if(inComment==0){
s[i-diff]=t[i];
}
s[i-diff+1]='\0';
++i;
}
countS=i-diff;
}
Thank you.
while(i<=countS){ t[i]=s[i];... }
Note that character strings are zero based. For example "ABC" has length 3, it starts at zero index, and the last valid index is 2 (not 3). Therefore you should change the condition to i < string_length
while(i < countS){ t[i]=s[i];... }
Also be careful when accessing t[i+1], because while i is valid, i+1 can be out of bound.
if (i < (countS - 1))
if(t[i]=='/' && t[i+1]=='*')
In order to assign one string to another, you can introduce a second variable k, and increment k after each assignment. This method is easier (in my opinion) than using the diff variable and doing additions and subtractions.
In addition, rather than char t[1000];, you can use char *t = malloc(countS); to declare a temporary variable of length countS, then it has to be freed at the end with free(t). If your compiler supports variable length array, you can just put char t[countS].
Example:
char s[1000]; //Principal array
int countS; //Number of char in array
//Functions 1
void deletMultiLineComments(void)
{
char *t = malloc(countS);
int i = 0;
int k = 0;
int inComment = 0;
while (i < countS)
{
t[i] = s[i];
++i;
}
i = 0;
while (i < countS)
{
if (i < countS - 1)
if (t[i] == '/' && t[i + 1] == '*')
{
inComment = 1;
i+=2;
continue;
}
if (inComment == 1)
{
if (i < countS - 1)
if (t[i] == '*' && t[i + 1] == '/')
{
inComment = 0;
i+=2;
continue;
}
}
if (inComment == 0)
{
s[k] = t[i];
k++;
}
++i;
}
free(t);
s[k] = '\0';
countS = k;
printf("mulitline comment removed %s\n", s);
}
//Function 2
void deletSingleLineComments(void)
{
char *t = malloc(countS);
int i = 0;
int k = 0;
int inComment = 0;
while (i < countS)
{
t[i] = s[i];
++i;
}
i = 0;
while (i < countS)
{
if (i < countS - 1)
if (t[i] == '/' && t[i + 1] == '/')
{
inComment = 1;
i += 2;
continue;
}
if (t[i] == '\n')
{
inComment = 0;
}
if (inComment == 0)
{
s[k] = t[i];
k++;
}
i++;
}
free(t);
s[k] = '\0';
countS = k;
printf("single comment removed %s\n", s);
}
int main(void)
{
//get input
scanf("%s", s);
countS = 0;
while (s[countS]) countS++;
deletMultiLineComments(); //Function 1
deletSingleLineComments(); //Function 2
}
I'm making a program that takes the characters from congress.txt makes them all uppercase, then "shifts them two characters", (A goes to C) (Z goes to B). But nothing is being printed, my main concern is if my arrays are being stored and passed to the different functions properly.
This is what is in congress.txt:
Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.
#include<stdio.h>
int processFile(int *store);
int cipher(int *store, int *code);
int outputCode(int *code);
int main(void){
int store[300], code[300], i;
processFile(store);
cipher(store, code);
outputCode(code);
getchar();
return 0;
}
void processFile(int *store){
int i, a = 0;
FILE *f = fopen("congress.txt", "r");
for (i = 0; a != EOF;){
fscanf(f, "%c", &a); //store character in a
if (a <= 'Z' && a >= 'A'){ //store uppercase letters
store[i] = a;
i++;
}
if (a <= 'z' && a >= 'a'){ //store lowercase letters as uppercase
store[i] = a - 32;
i++;
}
}
i++;
store[i] = '\0';
}
void cipher(int *store, int *code){
int i;
for (i = 0; store[i] != 0; ++i){
if (store[i] <= 'X' && store[i] >= 'A'){ //tests to see if the letter is between A and X
code[i] = (char)(store[i] + 2); //shifts letter by two characters
}
if (store[i] >= 'Y' && store[i] <= 'Z'){
code[i] = (char)(store[i] - 24); //shifts Y and Z to A or B respectively
}
}
}
void outputCode(int *code){
int i, a, b;
for (a = 0; code[a] != 0; ++a){
if (!(a % 50)){ //makes a newline every 50 characters
printf("\n");
}
for (b = 0; code[a] != 0 && b <= 5; ++b){ //prints chunks of 5 characters then makes a space
printf("%c", code[a]);
}
printf(" ");
}
}
There are several things wrong with your code - many of which your compiler will complain about.
To start - you don't have return values for functions that are declared int. Just make them void, or return something.
Second - you declare int a; but proceed to use it like a char. Declare it how you use it.
Third - testing for end of file is done with feof(f) not a != EOF.
Fourth - when you output your code you need to increment a, otherwise you get the same value five times:
VVVVVV JJJJJJ KKKKKK UUUUUU KKKKKK UUUUUU UUUUUU
etc.
Fifth - your printing routine doesn't guarantee it will stop - if you have a single '\0' followed by other garbage, you will print more garbage (unless it happens on a multiple of 5). You need to pad your cipher with zeros.
So - working code:
#include<stdio.h>
int processFile(int *store);
int cipher(int *store, int *code);
int outputCode(int *code);
int main(void){
int store[300], code[300], i;
processFile(store);
cipher(store, code);
outputCode(code);
printf("\n=====\n\n");
return 0;
}
int processFile(int *store){
int i;
char a = 0;
FILE *f = fopen("congress.txt", "r");
for (i = 0; !feof(f) && i<299;){
fscanf(f, "%c", &a); //store character in a
if (a <= 'Z' && a >= 'A'){ //store uppercase letters
store[i] = a;
i++;
}
if (a <= 'z' && a >= 'a'){ //store lowercase letters as uppercase
store[i] = a - 32;
i++;
}
}
store[i]='\0';
return 0;
}
int cipher(int *store, int *code){
int i;
for (i = 0; store[i] != 0; ++i){
if (store[i] <= 'X' && store[i] >= 'A'){ //tests to see if the letter is between A and X
code[i] = (char)(store[i] + 2); //shifts letter by two characters
}
if (store[i] >= 'Y' && store[i] <= 'Z'){
code[i] = (char)(store[i] - 24); //shifts Y and Z to A or B respectively
}
}
for(; i<300; i++) code[i]=0; // pad with zeros
return 0;
}
int outputCode(int *code){
int i, a, b;
for (a = 0; code[a] != 0; ++a){
if (!(a % 50)){ //makes a newline every 50 characters
printf("\n");
}
for (b = 0; code[a] != 0 && b <= 5; ++b){ //prints chunks of 5 characters then makes a space
printf("%c", code[a++]);
}
printf(" ");
}
return 0;
}
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;
}