I am trying to print each char of an array of matrices for a brick breaker game (the full message would be YOU LOSE). I am new to C and I don't feel too confident about using pointers; I feel that that may be the source of my problem. To try to solve the problem, I've read plenty of online guides on how to deal with strings in C; but the fact that I'm dealing with an array of arrays of arrays of chars makes this task quite a bit harder. If you know how to print matrices of strings (in yet another array) in C, or you have a better solution, please let me know!
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define LETTER_WIDTH 13
#define LETTER_HEIGHT 6
char Y[LETTER_HEIGHT][LETTER_WIDTH] = {
"___ __\n",
"\\ \\__ / /\n",
"\\ \\ / /\n",
"| | |\n",
"| | |\n",
"|__|__|\n"};
char O[LETTER_HEIGHT][LETTER_WIDTH] = {
" _______ \n",
" / __ \\\n",
"| | | |\n",
"| |__| |\n",
" \\_______/\n"};
char *SENTENCE[2][LETTER_HEIGHT][LETTER_WIDTH] = {*Y, *O};
void printLetter(char letter[LETTER_HEIGHT][LETTER_WIDTH]) {
for (int i = 0; i < LETTER_HEIGHT; i++) {
for (int j = 0; j < LETTER_WIDTH; j++) {
printf("%c", letter[i][j]);
}
}
}
void printSentence() {
for (int i = 0; i < 2; i++) {
char letter[LETTER_HEIGHT][LETTER_WIDTH];
strcpy(*letter, **SENTENCE[i]);
printLetter(letter);
sleep(1);
}
}
int main() {
printSentence();
return 0;
}
Firstly this should be better
char* Y[LETTER_HEIGHT] = {
"___ __\n",
"\\ \\__ / /\n",
"\\ \\ / /\n",
"| | |\n",
"| | |\n",
"|__|__|\n"};
char* O[LETTER_HEIGHT] = {
" _______ \n",
" / __ \\\n",
"| | | |\n",
"| |__| |\n",
" \\_______/\n"};
Now these are arrays of size 6 (you must add one line because O now have height of 5) containing pointers to arrays of chars. Next
char** SENTENCE[2] = {Y, O};
You did some really weird things with this line before, this defines SENTENCE as 2 element array of pointers to array of pointers to char arrays (which are Y and O).
Next
void printLetter(char** letter) {
for (int i = 0; i < LETTER_HEIGHT; i++) {
printf("%s", letter[i]);
}
}
This function takes pointer to array of pointers to char arrays. Then goes 6 times and print each array as string. Next
void printSentence() {
for (int i = 0; i < 2; i++) {
printLetter(SENTENCE[i]);
sleep(1);
}
}
Here you can use simple for loop to pass to printLetter each pointer to array of pointers to char arrays (which are these letters) from SENTENCE.
or you have a better solution, please let me know!
Yes, there is a much simpler and, I would argue, better solution, it's to place the SENTENCE in a single 2D array and print it in one go, even if you are to use ncurses, this makes your job easier.
Note that with ncurses you can reposition the cursor so you can print each letter separately in one line, you wouldn't need to join them together like you try to do in SENTENCE.
#define LETTER_WIDTH 100
#define LETTER_HEIGHT 6
char SENTENCE[LETTER_HEIGHT][LETTER_WIDTH] = {
"__ __ ______ \n",
"\\ \\ / / / __ \\\n",
" \\ \\/ / | | | |\n",
" | | | | | |\n",
" | | | |__| |\n",
" |__| \\______/\n"};
void printSentence()
{
for (int i = 0; i < 6; i++)
{
printf("%s", SENTENCE[i]);
}
}
Output:
__ __ ______
\ \ / / / __ \
\ \/ / | | | |
| | | | | |
| | | |__| |
|__| \______/
Related
Since I am kind of a beginner to programming, I try to programm as much as possible. I saw a illustration on how an integer array saves its bytes. I tried to make this illustration in c, just for the learning and I wondered if there is a better way than i did it.
The code below works on its own and if there is a more efficient way, it still should have the same output.
I know that my code would be very challenging if the array would have 100 integers.
#include <stdio.h>
int main() {
int lange = 3;
int c[lange];
c[0] = 3;
c[1] = 1;
c[2] = 2;
for (int i = 0; i < lange*4; i++) {
printf("| ");
if (i == 0) {
printf("%d", c[0]);
}
else if (i==4) {
printf("%d", c[1]);
}
else if (i==8){
printf("%d",c[2]);
}
}
return 0;
}
This could be done more compactly by changing the if-tree in the loop to be just
if ((i % 4) == 0)
printf("%d", c[i/4]);
or you could print every byte by doing something like
printf("%d", (c[i/4] >> (i%4 * 8)) & 0xff);
You should use a #define C_LEN 3 and use that instead of your magic number 3. You loop prints out a '|' in every iteration so your loop body cannot really be simplified other than:
if(!(i % 4)) printf("%d", c[i/4]);
If you only want to print something for 0, 4 and 8 then you iterate by 4 instead of 1, or better iterate by 1 (see below).
The output is:
| 3| | | | 1| | | | 2| | |
If that is all you want, I would write a single print statement:
printf("| %d| | | | %d| | | | %d| | | ", c[0], c[1], c[2]);
Or if you want a loop on group at a time and just iterate to 3 times:
for (int i = 0; i < C_LEN; i++) {
printf("| %d| | | ", c[i]);
}
It seems that you are trying to print the elements of the array, based on multiple of 4.
You can generalize your program by creating an array of any size and have your for loop like this:
int index = 0;
for (int i = 0; i < lange*4; i++)
{
printf("| ");
if (i == 0)
{
index = 0;
}
else if((i % 4) == 0)
{
index = i/4;
}
else
{
continue;
}
printf("%d",c[index]);
}
I am trying to print a series of multi-line strings (ascii art letters here), and when printing them out, the top of each letter moves to the right while the rest of the letter stays in the same position. Here is a screenshot of what occurs:
I do not know why this is happening, as I am fairly new to C; if you have any knowledge about this, please share it!
#include <stdio.h>
#include <curses.h>
typedef const char letter[];
letter Y =
"___ __\n
\\ \\__ / /\n
\\ \\ / /\n
| | |\n
| | |\n
|__|__|\n";
letter O =
"_______ \n
/ __ \\\n
| | | |\n
| |__| |\n
\\_______/\n";
letter U =
" __ __ \n
/ | | \\\n
| | | |\n
| \\_/ |\n
\\_________/\n";
letter L =
" _\n"
"| |\n"
"| |\n"
"| |__\n"
"|____/\n";
letter S =
" _________\n"
"/ _____/\n"
"\\_____ \\\n"
"/ \\\n"
"/_______ /\n"
" \\/\n";
letter T =
"___________\n"
"\\__ ___/\n"
" | |\n"
" | |\n"
" |___|\n";
letter EXCLAMATION_POINT =
"_________\n"
"\\\\\\\\|////\n"
" \\\\\\|///\n"
" \\\\|//\n"
" \\|/\n"
" ***\n"
" ***\n"
" *\n";
const char *MESSAGE[] = {Y, O, U, L, O, S, T, EXCLAMATION_POINT};
int main() {
initscr();
cbreak();
noecho();
int maxY, maxX;
getmaxyx(stdscr, maxY, maxX);
int spacingPerLetter = maxX / 8;
for (int i = 0; i < 8; i++) {
mvprintw(maxY / 2, spacingPerLetter * (i + 1), MESSAGE[i]);
refresh();
getch();
clear();
}
endwin();
return 0;
}
The main problem is the newline embedded inside the strings you print.
The first "line" of the letters will be printed in the correct position, but then the newline will reset the position to the first column on the next line.
I recommend that you print each "letter" line by line (without the newlines). This could be helped by having each "letter" be an array of arrays of characters, where each sub-array is one line of the letter:
#define LETTER_WIDTH 11
#define LETTER_HEIGHT 6
const char Y[LETTER_HEIGHT][LETTER_WIDTH] = {
"___ __",
"\\ \\__ / /",
" \\ \\ / / ",
" | | | ",
" | | | ",
" |__|__| "
};
This question already has answers here:
printing a square with diagonals
(4 answers)
Closed 3 years ago.
Guys i'm pretty stuck here. I'm trying to learn c and create some very basic code which asks the user to insert a number. Then, this number enters the following formula : 2x+1, then I want it to print a hollow square pattern with a different symbol for rows and columns, and add a + in the corners, diagonals, and a "X" in the middle.
I'm stuck in the very very beginning of the code. I don't know where should I even start. I mean I can't even learn how to make different symbols for the rows and columns.
I'm trying to learn and study it for 3 hours already, watched 20 different YouTube videos and read 20 different coding guides.
It's so frustrating..
Thanks.
I'm attaching a picture of my code & my output, and the desired output on the right.
the code itself:
int size;
printf("Please enter a number that will define the size of the square: \n");
scanf("%d", &size);
size = 2 * size + 1;
for (int i = 1; i <= size-2; i++) {
for (int j = 1; j <= size-2; j++) {
if (j == 1 || j == size - 1) {
printf("|");
}
else {
printf(" ");
}
if (i==1 || i==size-2){
printf("-");
}
else {
printf(" ");
}
}
printf("\n");
}
#include <stdio.h>
int main(void) {
int size;
printf("Please enter a number that will define the size of the square: \n");
scanf("%d", &size);
size = 2 * size + 1;
const char *spaces=" ";
const char *dashes="-----------------------------------------";
printf("+%.*s+\n", size, dashes);
for(int i=1; i<size/2+1; ++i)
{
printf("|%.*s\\%.*s/%.*s|\n", i-1, spaces, size-2*i, spaces,i-1, spaces);
}
printf("|%.*sX%.*s|\n", size/2, spaces, size/2, spaces);
for(int i=size/2+1; i<size; ++i)
{
printf("|%.*s/%.*s\\%.*s|\n", size-i-1, spaces, 2*(i-size/2)-1, spaces, size-i-1, spaces);
}
printf("+%.*s+\n", size, dashes);
return 0;
}
Example Run:
Please enter a number that will define the size of the square: 8
Success #stdin #stdout 0s 4568KB
+-----------------+
|\ /|
| \ / |
| \ / |
| \ / |
| \ / |
| \ / |
| \ / |
| \ / |
| X |
| / \ |
| / \ |
| / \ |
| / \ |
| / \ |
| / \ |
| / \ |
|/ \|
+-----------------+
I used this program to take input mm as the month of the year and print out the name of the month:
#include <stdio.h>
#include <string.h>
int main(){
int mm;
printf("input month ");
scanf("%d", &mm);
char mname[9];
if (mm == 1) {mname = "January";}
if (mm == 2) {mname = "February";}
if (mm == 3) {mname = "March";}
if (mm == 4) {mname = "April";}
if (mm == 5) {mname = "May";}
if (mm == 6) {mname = "June";}
if (mm == 7) {mname = "July";}
if (mm == 8) {mname = "August";}
if (mm == 9) {mname = "September";}
if (mm == 10) {mname = "October";}
if (mm == 11) {mname = "November";}
if (mm == 12) {mname = "December";}
printf("%d is month %s", mm, mname);
return 0;
}
it gave an error assignment to expression with array type. please help
Taking Michael Walz two great comments and adding them as an answer:
#include <stdio.h>
#include <string.h>
void main(int argc, char** argv)
{
int mm = 0;
printf("Please enter a month number [1-12]:\n");
scanf("%d", &mm);
static const char* months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
if (mm >= 1 && mm <= 12)
{
printf("%d is month %s", mm, months[mm - 1]);
}
else
{
printf("You have entered an invalid month number %d\n", mm);
}
}
Validity check was done (mentioned in above comments).
Hope it helps.
Cheers,
Guy.
Basically there are two different ways to think about / talk about strings:
An array of characters, terminated by a '\0' character. (This is the formal definition of a string in C.)
As a pointer to character, or char *, pointing at the first of a sequence (an array) of characters, terminated by a '\0' character.
So you can declare an array, and copy a string into it:
char arraystring[10];
strcpy(arraystring, "Hello");
Or you can declare an array, and give it an initial value when you declare it:
char arraystring2[] = "world!";
Or you can declare a pointer, and make it point to a string:
char *pointerstring;
pointerstring = "Goodbye";
Or you can declare a pointer, and give it an initial value:
char *pointerstring2 = "for now";
It's worth knowing how these "look" in memory:
+---+---+---+---+---+---+---+---+---+---+
arraystring: | H | e | l | l | o |\0 |\0 |\0 |\0 |\0 |
+---+---+---+---+---+---+---+---+---+---+
+---+---+---+---+---+---+---+
arraystring2: | w | o | r | l | d | ! |\0 |
+---+---+---+---+---+---+---+
+---------------+
pointerstring: | * |
+-------|-------+
| +---+---+---+---+---+---+---+---+
+---------> | G | o | o | d | b | y | e |\0 |
+---+---+---+---+---+---+---+---+
+---------------+
pointerstring2: | * |
+-------|-------+
| +---+---+---+---+---+---+---+---+
+---------> | f | o | r | | n | o | w |\0 |
+---+---+---+---+---+---+---+---+
Now, the thing is, you can't assign arrays in C. You can assign pointers. You can also make use of the special rule (the "equivalence between arrays and pointers") by which when you use an array in an expression, what you get is a pointer to the array's first element.
So if you want to assign one string-as-pointer to another string-as-pointer, that works:
pointerstring = pointerstring2;
If you try to assign one string-as-array to another string-as-array, that doesn't work
arraystring = arraystring2; /* WRONG -- compiler complains, attempt to assign array */
If you want to copy one string-as-array to another, you have to call strcpy (and of course you have to worry about overflow):
strcpy(arraystring, arraystring2);
You can also assign a string-as-array to a string-as-pointer:
pointerstring = arraystring;
This works because the compiler treats it exactly as if you'd written
pointerstring = &arraystring[0];
Finally, if you attempt to assign a string-as-pointer to a string-as-array, this doesn't work, again because you can't assign to an array:
arraystring = pointerstring; /* WRONG */
Again, you could call strcpy instead, as long as you're sure the string will fit:
strcpy(arraystring, pointerstring); /* but worry about overflow */
In your original code, mname was a string-as-array, so you can't assign to it. You have two choices:
Use strcpy to copy strings into it:
if (mm == 1) { strcpy(mname, "January"); }
Declare mname as p a pointer instead:
char *mname;
...
if (mm == 1) { mname = "January"; }
Addendum: For completeness, I should mention one more set of points.
When you initialize a pointer to point to a string, in either of these ways:
char *pointerstring = "Goodbye";
char * pointerstring2;
pointerstring2 = "for now";
those strings "Goodbye" and "for now" are read-only. You can't modify them. So if you try to do something like
strcpy(pointerstring, pointerstring2); /* WRONG: overwriting constant string */
it won't work, because you're trying to copy the second string into the memory where the first string is stored, but that memory isn't writable.
So when you're using arrays, you can't use assignment, you must use strcpy; but when you're using pointers, you can use assignment, and you probably can't call strcpy.
Basically array types are constant pointers, so when you try to assign a new value to pointer mname the compiler detects an error.
You could use function strcpy as in the following example to solve the problem:
if (mm == 1) {
strcpy(mname, "January");
}
I recently created a program that calculates flow rate through a pipe and generates, line by line, a scatter graph of the output. My knowledge of C is rudimentary (started with python) and I get the feeling that I may have made the code overly complicated. As such, I am asking if anyone has any alternatives to the code below. Critiques of code structure etc. are also welcome!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define PI 3.1415926
double
flow_rate(double diameter, double k, double slope){
double area, w_perimeter, hyd_rad, fr;
area = (PI*pow(diameter,2.0))/8.0;
w_perimeter = (PI*diameter)/2.0;
hyd_rad = area/w_perimeter;
fr = (1.0/k)*area*pow(hyd_rad,(2.0/3.0))*pow(slope,(1.0/2.0));
return fr;
}
int
main(int argc, char **argv) {
double avg_k=0.0312, min_slope=0.0008;
float s3_diameter;
int i=0, num=0, flow_array[6] ,rows, align=29;
char graph[] = " ";
char graph_temp[]= " ";
printf("\nFlow Rate (x 10^-3) m^3/s\n");
for (s3_diameter=0.50;s3_diameter>0.24;s3_diameter-=0.05){
flow_array[i] = (1000*(flow_rate(s3_diameter, avg_k, min_slope))+0.5);
i += 1;
}
for (rows=30;rows>0;rows--){
strcpy(graph_temp,graph);
for (num=0;num<6;num++){
if (rows==flow_array[num] && rows%5==0){
graph_temp[align] = '*';
printf("%d%s\n",rows,graph_temp);
align -= 5;
break;
}
else if (rows==flow_array[num]){
graph_temp[align] = '*';
printf("|%s\n",graph_temp);
align -= 5;
break;
}
else {
if (rows%5==0 && num==5){
printf("%d%s\n",rows,graph_temp);
}
else if (rows%5!=0 && num==5){
printf("|%s\n",graph_temp);
}
}
}
}
printf("|----2----3----3----4----4----5----\n");
printf(" 5 0 5 0 5 0\n");
printf(" Diameter (x 10^-2) m\n");
return 0;
}
Output as below.
Flow Rate (x 10^-3) m^3/s
30
|
|
|
|
25
|
|
| *
|
20
|
|
| *
|
15
|
|
| *
|
10
| *
|
|
| *
5
| *
|
|
|
|----2----3----3----4----4----5----
5 0 5 0 5 0
Diameter (x 10^-2) m
GNUPlot is by far the simplest way to draw graph in C.
It can draw from simple plotting to complex 3d graph, and even provides an ASCII Art output (if ASCII output is really required)
You can find more information on how to use GNUPlot in a C program here: http://ndevilla.free.fr/gnuplot/