How would I output to a file using multiple chars - c

#define numeric_b '0'
#define numeric_e '9'
/** init string intervals ---*/
static char c0=numeric_b;
static char c1=numeric_b;
static char c2=numeric_b;
static char c3=numeric_b;
static char c4=numeric_b;
static char c5=numeric_b;
static char c6=numeric_b;
static char c7=numeric_b;
/** init start & end ----------------*/
static const char en = numeric_e +1;
static const char st = numeric_b +1;
void str_in(int length){
FILE * fp = fopen("list.txt","w");
switch(length){
case 0:
printf("%c\n",c0);break;
case 1:
printf("%c%c\n",c0,c1);break;
case 2:
printf("%c%c%c\n",c0,c1,c2);break;
case 3:
printf("%c%c%c%c\n",c0,c1,c2,c3);break;
case 4:
printf("%c%c%c%c%c\n",c0,c1,c2,c3,c4);break;
case 5:
printf("%c%c%c%c%c%c\n",c0,c1,c2,c3,c4,c5);break;
case 6:
printf("%c%c%c%c%c%c%c\n",c0,c1,c2,c3,c4,c5,c6);break;
case 7:
printf("%c%c%c%c%c%c%c%c\n",c0,c1,c2,c3,c4,c5,c6,c7);break;
}
fclose(fp);
}
void permute(int length){
while(c0<=en){
str_in(length);
c0++;
if(c0==en && length==0){break;}
if(c0==en){
c0=st;
c1++;
if(c1==en && length==1){break;}
if(c1==en){
c1=st;
c2++;
if(c2==en && length==2){break;}
if(c2==en){
c2=st;
c3++;
if(c3==en && length==3){break;}
if(c3==en){
c3=st;
c4++;
if(c4==en && length==4){break;}
if(c4==en){
c4=st;
c5++;
if(c5==en && length==5){break;}
if(c5==en){
c5=st;
c6++;
if(c6==en && length==6){break;}
if(c6==en){
c6=st;
c7++;
if(c7==en && length==7){break;}
}
}
}
}
}
}
}
}
}

Sorry #zartag but this is some seriously obfuscated code. Please just tell us in a paragraph what you're trying to do and what you think your code is doing.
The most obvious thing I can see wrong with your code with respect to the question title ("output to a file") is that you are using printf instead of fprintf. They behave almost identically, except that printf prints to standard output, and fprintf prints to a file stream (e.g. to your list.txt). See the documentation on fprintf. In your case it should be
FILE * fp = fopen("list.txt","w");
switch(length){
case 0:
fprintf(fp, "%c\n",c0);break;
..snip
But seriously that code is in dire need of refactoring (e.g. it looks like the whole switch block can be replaced with a for loop). And please, when you ask a question here, give us a little more to go on than a code listing and question title.

Related

(C) Am I properly converting enum type to string?

I am very new to coding, and am taking an online course with very little help. I am working through an assignment creating a bunch of functions that will be used at a later date. I have not learned anything about points, arrays, or recursions at this point. My knowledge of strings is pretty much limited to the "printf" function.
With that being said, I have been given this description for how the function "ranking_to_string" should operate:
This function should convert the
hand_ranking_t enumerated value passed
in to a string that describes it.
The enumerated type here is hand_ranking_t, which ranks a poker hand in descending order of value from STRAIGHT_FLUSH (0) to NOTHING (8). With that all being said, this is the function I have created to attempt to follow my instructions:
const char * ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: printf("STRAIGHT_FLUSH\n"); break;
case FOUR_OF_A_KIND: printf("FOUR_OF_A_KIND\n"); break;
case FULL_HOUSE: printf("FULL_HOUSE\n"); break;
case FLUSH: printf("FLUSH\n"); break;
case STRAIGHT: printf("STRAIGHT\n"); break;
case THREE_OF_A_KIND: printf("THREE_OF_A_KIND\n"); break;
case TWO_PAIR: printf("TWO_PAIR\n"); break;
case PAIR: printf("PAIR\n"); break;
case NOTHING: printf("NOTHING\n"); break;
default: printf("Invalid thing\n"); break;
}
return EXIT_SUCCESS;
}
I am wondering, am I correct in returning EXIT_SUCCESS (0) at the end of the function? Is there another way to convert the enum value entered into a string using printf?
EXIT_SUCCESS is a macro that will expand into an environment defined indicator to be returned from main (or via exit, etc.) to indicate that your entire program has successfully done what it is supposed to do. It's generally not used outside this context.
printf is used to send output to the stream associated with stdout. For example, you might call printf to display text in your terminal.
Your function should instead return the string literals, to be used by the caller of ranking_to_string.
const char *ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: return "STRAIGHT_FLUSH";
case FOUR_OF_A_KIND: return "FOUR_OF_A_KIND";
/* ... and so on ... */
default: return "Invalid thing";
}
}
An example program:
#include <stdio.h>
typedef enum {
STRAIGHT_FLUSH,
FOUR_OF_A_KIND,
/* ... and so on ... */
} hand_ranking_t;
const char *ranking_to_string(hand_ranking_t r) {
switch (r) {
case STRAIGHT_FLUSH: return "STRAIGHT_FLUSH";
case FOUR_OF_A_KIND: return "FOUR_OF_A_KIND";
/* ... and so on ... */
default: return "Invalid thing";
}
}
int main(void) {
hand_ranking_t rank = FOUR_OF_A_KIND;
const char *rank_string = ranking_to_string(rank);
printf("My ranking is <%s>\n", rank_string);
}
Output:
My ranking is <FOUR_OF_A_KIND>
Probably not covered in your course, but it's possible to automate ranking_to_string entirely by using X-Macros. Also, since poker hands have value, it makes sense to list them by it.
#include <stdlib.h>
#include <stdio.h>
#define HANDS X(HIGH_CARD), X(PAIR), X(TWO_PAIR), X(THREE_OF_A_KIND), \
X(STRAIGHT), X(FLUSH), X(FULL_HOUSE), X(FOUR_OF_A_KIND), \
X(STRAIGHT_FLUSH), X(ROYAL_FLUSH)
#define X(name) name
enum hand { HANDS };
#undef X
#define X(name) #name
static const char *hand_str[] = { HANDS };
#undef X
static const size_t hand_size = sizeof hand_str / sizeof *hand_str;
int main(void) {
enum hand i, j;
for(i = 0; i < hand_size; i++) printf("%s\n", hand_str[i]);
i = FULL_HOUSE;
j = FLUSH;
printf("%s is %s than %s.\n",
hand_str[i], i < j ? "less" : "greater", hand_str[j]);
return EXIT_SUCCESS;
}
Where # is the stringizing operator of the pre-processor.

can we use switch-case statement with strings in c? [duplicate]

This question already has answers here:
How can I compare strings in C using a `switch` statement?
(16 answers)
Closed 5 years ago.
int a = 0 , b = 0;
char* c = NULL;
int main(int argc , char ** argv){
c = argv[2];
a = atoi(argv[1]);
b = atoi(argv[3]);
switch(c){
case "+": printf(a+b);
break;
}
printf("\n\n");
return 0;
}
No, you can't. Switch is intended to compare numeric types, and for extension char types.
Instead you should use the strcmp function, included in string header:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
if (argc != 4) {
puts("Incorrect usage");
return 1;
}
/* You should check the number of arguments */
char * op = argv[1];
int a = atoi(argv[2]);
int b = atoi(argv[3]);
/* You should check correct input too */
if (strcmp(op, "+") == 0)
printf("%d + %d = %d\n", a, b, a + b);
else if (strcmp(op, "-") == 0)
printf("%d - %d = %d\n", a, b, a - b);
/* Add more functions here */
return 0;
}
No you can't. The case labels of a switch need to be compile time evaluable constant expressions with an integral type.
But int literals like '+' satisfy that requirement. (As do enum values for that matter.)
Some folk like to use implementation-defined multi-character literals (e.g. 'eax') as case labels as they claim it helps readability, but at that point, you're giving up consistent behaviour across different platforms.
If you need to branch on the value of a NUL-terminated char array, then use an if block.
There are two cases to the answer ..
Firstly 6.8.4.2 (switch case)
The controlling expression of a switch statement shall have integer
type
Secondly 6.8.4.2 (the case statements)
The expression of each case label shall be an integer constant
expression and no two of the case constant expressions in the same
switch statement shall have the same value after conversion
Long story short - you can't use string literal like that. Neither in switch controlling expression nor in case.
You can do the string comparisons using strcmp and then do the if-else conditioning. The context on which you ask this, you can simply pass the character + (argv[2][0]) instead of passing the whole literal. That way you will be passing char to the switch expression and then work accordingly.
Nope, that's not possible.
Quoting C11, chapter §6.8.4.2
The controlling expression of a switch statement shall have integer type.
in your case, you don't seem to need a string but rather the first (and only character) of the string passed in the switch statement, in that case that's possible using character literal (which has integer type) in the case statements:
if (strlen(c)==1)
{
switch(c[0]){
case '+': printf(a+b);
break;
...
}
}
some good other alternatives are described in best way to switch on a string in C when the string has multiple characters.
Not directly. But yes, you can.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
// The way you store and search for names is entirely
// up to you. This is a simple linear search of an
// array. If you have a lot of names, you might choose
// a better storage + lookup, such as a hash table.
int find( const char** ss, int n, const char* s )
{
int i = 0;
while (i < n)
if (strcmp( ss[i], s ) == 0) break;
else i += 1;
return i;
}
// A bevvy of little utilities to help out.
char* strupper( char* s )
{
char* p = s;
while ((*p = toupper( *p ))) ++p;
return s;
}
char* zero( char* p ) { if (p) *p = 0; return p; }
#define STRINGIFY(S) STRINGIFY0(S)
#define STRINGIFY0(S) #S
int main()
{
// Our list of names are enumerated constants with associated
// string data. We use the Enum Macro Trick for succinct ODR happiness.
#define NAMES(F) \
F(MARINETTE) \
F(ADRIAN) \
F(ALYA) \
F(DINO)
#define ENUM_F(NAME) NAME,
#define STRING_F(NAME) STRINGIFY(NAME),
enum names { NAMES(ENUM_F) NUM_NAMES };
const char* names[ NUM_NAMES ] = { NAMES(STRING_F) NULL };
#undef STRING_F
#undef ENUM_F
#undef NAMES
// Ask user for a name
char s[ 500 ];
printf( "name? " );
fflush( stdout );
fgets( s, sizeof( s ), stdin );
zero( strchr( s, '\n' ) );
// Preprocess and search for the name
switch (find( names, sizeof(names)/sizeof(*names), strupper( s ) ))
{
case MARINETTE: puts( "Ladybug!" ); break;
case ADRIAN: puts( "Chat Noir!" ); break;
case ALYA:
case DINO: puts( "Best friend!" ); break;
default: puts( "Who?" );
}
}
Keep in mind this works by pure, unadulterated magic tricks, and is not suitable for large collections of text values.
Also, the validity of the match is entirely dependent on the degree to which you pre-process the user’s input. In this example we only ignore case, but a more advanced application might perform some more sophisticated matching.
As others pointed out in C one cannot use a string as argument to a switch, nor to its case-labels.
To get around this limitation one could map each string to a specific integer and pass this to the switch.
Looking up the mapping requires searching the map, which can be done using the Standard C bsearch() function.
An example might look like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>
enum Operation {
OP_INVALID = -1,
OP_ADD,
OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_MAX
};
struct Operation_Descriptor {
char * name;
enum Operation op;
};
struct Operation_Descriptor operations [] = {
{"add", OP_ADD},
{"subtract", OP_SUBTRACT},
{"multiply", OP_MULTIPLY},
{"divide", OP_DIVIDE}
};
int cmp(const void * pv1, const void * pv2)
{
const struct Operation_Descriptor * pop1 = pv1;
const struct Operation_Descriptor * pop2 = pv2;
return strcmp(pop1->name, pop2->name);
}
int main(int argc, char ** argv)
{
size_t s = sizeof operations / sizeof *operations;
/* bsearch() requires the array to search to be sorted. */
qsort(operations, s, sizeof *operations, cmp);
{
struct Operation_Descriptor * pop =
bsearch(
&(struct Operation_Descriptor){argv[1], OP_INVALID},
operations, s, sizeof *operations, cmp);
switch(pop ?pop->op :OP_INVALID)
{
case OP_ADD:
/* Code to add goes here, */
break;
case OP_SUBTRACT:
/* Code to subtract goes here, */
break;
case OP_MULTIPLY:
/* Code to multiply goes here, */
break;
case OP_DIVIDE:
/* Code to divide goes here, */
break;
case OP_INVALID:
default:
fprintf(stderr, "unhandled or invalid operation '%s'\n", argv[1]);
break;
}
}
}
If on POSIX one can even use a hash table, which is the fastest way to lookup the mapping.
An example might look like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>
enum Operation {
OP_INVALID = -1,
OP_ADD,
OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_MAX
};
struct Operation_Descriptor {
char * name;
enum Operation op;
};
struct Operation_Descriptor operations [] = {
{"add", OP_ADD},
{"subtract", OP_SUBTRACT},
{"multiply", OP_MULTIPLY},
{"divide", OP_DIVIDE}
};
int main(int argc, char ** argv)
{
if (0 == hcreate(5))
{
perror("hcreate() failed");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < s; ++i)
{
if (!hsearch((ENTRY){operations[i].name, &operations[i].op}, ENTER))
{
perror("hsearch(ENTER) failed");
exit(EXIT_FAILURE);
}
}
{
ENTRY * ep = hsearch((ENTRY){argv[1], NULL}, FIND);
switch(ep ?*((enum Operation *)ep->data) :OP_INVALID)
{
case OP_ADD:
/* Code to add goes here, */
break;
case OP_SUBTRACT:
/* Code to subtract goes here, */
break;
case OP_MULTIPLY:
/* Code to multiply goes here, */
break;
case OP_DIVIDE:
/* Code to divide goes here, */
break;
case OP_INVALID:
default:
fprintf(stderr, "unhandled or invalid operation '%s'\n", argv[1]);
break;
}
}
hdestroy(); /* Clean up. */
}

Switch statement using a union in C, got me into problems, what's wrong with my code?

I'm almost done with my assignment where I was supposed to build a program where the user interacts with a warehouseprogram, where you can delete, add, edit... However in my event_loop function, no matter what input I type to choose from the menu goes to default in my switch statement. I'm using a uniontype answer_t in my ask_question_menu, so maybe it has something to do with the return from that function that I want to be a single char. Can someone tell me what the heck is going on here?
Very thankful for help!
typedef union {
int i;
float f;
char *s;
char d;
} answer_t;
char ask_question_menu(char *question){
answer_t answer = ask_question(question, correct_input, (convert_func) toupper);
return answer.d;
}
//my general function for user input follows here...
answer_t ask_question(char *question, check_func check, convert_func convert)
{
int buffersize = 50;
char buffer[buffersize];
do
{
printf("%s\n", question);
read_string(buffer, buffersize);
}
while(check(buffer)==false);
answer_t result = convert(buffer);
return result;
}
int event_loop(item_t *db, int *db_size)
{
while(true){
char choise = ask_question_menu(" [L]ägga till en vara\n [T]a bort en vara\n [R]edigera en vara\n Ån[g]ra senaste ändringen\n Lista [h]ela varukatalogen\n [A]vsluta\n");
switch(choise)
{
case 'L':
add_item_to_db(db, db_size);
break;
case 'T':
remove_item_from_db(db, db_size);
break;
case 'R':
edit_db(db, *db_size);
break;
case 'G':
printf("Not yet implemented\n");
break;
case 'H':
list_db(db, *db_size);
case 'A':
return 0;
break;
default:
printf("Wrong input\n");
break;
}
}
}
When convert points to toupper(), this line ...
answer_t result = convert(buffer);
... definitely produces undefined behavior, because toupper() takes a parameter of type int and returns an int, but you are passing a char * and assuming that the return value is an answer_t. If you prefer, you can say that it is the cast of toupper to convert_func that is ultimately responsible for this UB.
If you need a function that returns an answer_t, then you'll need to wrap toupper(). It's unclear exactly what form a convert_func is supposed to have, but this would be compatible with the way you are trying to use it:
answer_t toupper_wrap(char *buffer) {
return (answer_t) { .d = toupper(*buffer) };
}
Pass a pointer to that instead of a pointer directly to toupper().

Getting choice from input

I want to prompt the user to press a key.This key will be stored in a variable and a switch statement is applied on the key to execute the corresponding command.I wrote a code,which seems a bit nasty and inefficient because it makes a call to the function GetAsyncKeyState in an exhausting way,specially if the keys are too many.Is there a simpler approach to this?
#include <stdio.h>
#include <Windows.h>
int GetChoice(int *keys,size_t size);
int main(void)
{
int keys[] = {'A','B','F'};
int cKey = GetChoice(keys,3);
switch(cKey)
{
case 'A':
puts("you pressed : A!");
break;
case 'B':
puts("you pressed : B!");
break;
case 'F':
puts("you pressed : F!");
break;
}
Sleep(2000);
return 0;
}
int GetChoice(int *keys,size_t size)
{
size_t n;
while(1)
{
for(n = 0 ; n < size ; n++)
{
if(GetAsyncKeyState(keys[n]))
return keys[n];
}
}
return 0;
}
Well you need to only change from
int cKey = GetChoice(keys,3);
to
char cKey;
cKey=getch();
you do not need the
int GetChoice(int *keys,size_t size)
function. Just remove it too. Your entire code should look like
#include <stdio.h>
#include<conio.h>
int main(void)
{
char cKey;
cKey=getch();
switch(cKey)
{
case 'A':
puts("you pressed : A!");
break;
case 'B':
puts("you pressed : B!");
break;
case 'F':
puts("you pressed : F!");
break;
}
Sleep(2000);
return 0;
}
You are mixing apples and oranges. If you output messages with puts(), you should probably read input from standard input with getchar(). Reading the keyboard state with GetAsyncKeyState() is only consistent if you display information on the screen using the Windows API. Doing this in C has gone out of fashion a long time ago already. Good luck!
If you're trying to program in C, use C constructs, not Windows constructs. Take a look at K&R (Kernighan and Ritchie) section 1.5. K&R is available in PDF form. Just search for it.
If you use the async key state, you will have to apply your own detection for liftoff.

Why can't I get string input?

I was trying to simulate stack concept, and this is my code, blasts errors everywhere, from
the very first scanf,
to everywhere referring char* variables,
and eventually the stack pointer (I named it towerIndicator) doesn't change at all.
And then every typed input is somehow screwed: if I type '+314' to add 314 to the stack, it eventually add 3144, if all the problem above were somehow prevented while compiling.
gcc doesn't inform me any usable error message so I don't get where to go at all. Desperately requiring help here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const int towerHeight = 32;
int tower[towerHeight];
int towerIndicator = 0;
/*
printf("%i개의 정수를 담을 수 있는 스택을 만들었습니다.\n", towerHeight);
printf("- '+'를 붙여서 정수를 담습니다.\n");
printf("- '-'를 입력해 정수를 빼냅니다.\n");
printf("- '?'를 입력해 스택을 확인합니다.\n");
printf("- '0'를 입력해 작업을 종료합니다.\n");
printf("명령을 입력해주세요.\n================================\n");
*/
char* command;
char* kindOfCommand[1];
char* actualCommand;
while(1) {
printf("> ");
scanf("%s", command);
printf("%s", command);
strncpy(*kindOfCommand, command, 1); kindOfCommand[1] = '\0';puts("#");
strncpy(actualCommand, command+1, strlen(command)-1);puts("$");
switch(**kindOfCommand) {
int i;
case '+':
if(towerIndicator<towerHeight) {
tower[towerIndicator] = atoi(actualCommand);
towerIndicator++;
printf("현재 %i개의 값이 있습니다.\n", towerIndicator);
} else printf("더 이상 넣을 곳이 없습니다.\n");
break;
case '-':
if(towerIndicator>0) {
towerIndicator--;
printf("%i\n", tower[towerIndicator]);
printf("현재 %i개의 값이 있습니다.\n", towerIndicator);
} else printf("더 이상 빼낼 값이 없습니다.\n");
break;
case '?':
default:
printf("[");
for(i=0; i<towerIndicator; i++) {
if(i==towerIndicator) printf("[%i]", tower[i]);
else printf("%i", tower[i]);
if(i!=towerIndicator-1) printf(" ");
}
printf("]\n");
break;
}
if(**kindOfCommand=='0') break;
}
}
There are quite a few modifications required here
loosely fixed may be in for a lot more fixes
// char* command; // <-- initialize this, failure in scanf other wise
char command[120] ;
assuming you are looking for a single character, don't complicate code
// char* kindOfCommand[1]; pointer not required
char kindOfCommand;
since you are using strncpy down somewhere
// char* actualCommand; // <-- initialize this
char actualCommand[126];
and the kindOfCommand code change
// strncpy(kindOfCommand, command, 1);
kindOfCommand = *command;// since you are taking single character
puts("#");
some more at switch
switch( kindOfCommand ) {
and while breaking
if( kindOfCommand == '0' ) break;
Also return before end
return 0;
I applied changes from kkk's answer, and getting input now works well.
char command[11];
char kindOfCommand;
char actualCommand[10];
while(1) {
printf("> ");
scanf("%s", command);
kindOfCommand = *command;
memset(actualCommand,0,sizeof(actualCommand));
strncpy(actualCommand, command+1, strlen(command)-1);
switch(kindOfCommand) { ... }
...
if(kindOfCommand=='0') break;
}
return 0;
}
I needed to solve the input getting screwed. It was because when actualCommand receives a new string from command and it's shorter than previous received string, the last few characters of the string was still remaining in actualCommand. So I put a memset to reset the variable every time the while loop loops. It's not a pointer, so sizeof() could do the work. Otherwise I should've to use strlen() to tell memset the length.

Resources