Csh script call C program,arguments issue - c

This the line from the csh script
./model2grd $model -D$nx/$ny/$nz -O$x0/$y0 -I$dx/$dy -L$layer -C$coverage -Avel.dat -Gvel.grd
This is part of the model2grd.c
for (i = 2; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
case 'C':
cov = &argv[i][2];
lcov = TRUE;
break;
case 'A':
xyzfile = &argv[i][2];
lxyz = TRUE;
break;
case 'D':
sscanf(&argv[i][2],"%d/%d/%d",&nx,&ny,&nz);
break;
case 'I':
sscanf(&argv[i][2], "%lf/%lf", &dx, &dy);
break;
case 'O':
sscanf(&argv[i][2], "%lf/%lf", &xmin, &ymin);
break;
case 'L':
layer = atoi(&argv[i][2]);
break;
case 'N':
nan = (float)atof(&argv[i][2]);
break;
case 'Z':
cvalue = (float)atof(&argv[i][2]);
break;
case 'V':
verbose = TRUE;
break;
default:
break;
}
}
}
Does this mean that it takes with D(nx,ny,nz),with O(xmin and ymin),with L layer and with C coverage?Are Avel.dat and Gvel.grd input files or not?

Avel.dat and Gvel.grd are not input files. Look at the argument parsing again.
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
Consider that with this argument:
-Gvel.grd
In plain English, the switch examines the second character of each argument. In this case -Gvel.grd is the argument, so it looks at the G. Passing that test, the case statement then derives the address of the character that comes immediately after the G within the character string. In other words, the v.
Therefore, the file name is actually vel.grd. You should be able to apply this same logic to the rest of the arguments that follow the same pattern.

Related

Convert phone number from alphabetic to numeric form

I'm doing an exercise from KNKings book "C Programming: A modern approach" which involves converting a phone number in alphabetic form, entered by the user, into numeric form. When the program encounters non-alphabetic characters (digits or punctuations, for example), it should leave them unchanged. I may assume that the user only enters upper-case letters.
However, my program seems to produce garbage, to say the least.
#include <stdio.h>
#define MAX_SIZE 50
int main(void)
{
char alphabetic[MAX_SIZE], ch;
int num_elements = 0;
printf("Enter phone number: ");
int i;
for (i = 0; i < MAX_SIZE && ((ch = getchar()) != '\n'); i++){
alphabetic[i] = ch;
num_elements++;
}
for (i = 0; i <= num_elements; i++){
switch (alphabetic[i]){
case 'A': case 'B': case 'C': alphabetic[i] = '2'; break;
case 'D': case 'E': case 'F': alphabetic[i] = '3'; break;
case 'G': case 'H': case 'I': alphabetic[i] = '4'; break;
case 'J': case 'K': case 'L': alphabetic[i] = '5'; break;
case 'M': case 'N': case 'O': alphabetic[i] = '6'; break;
case 'P': case 'R': case 'S': alphabetic[i] = '7'; break;
case 'T': case 'U': case 'V': alphabetic[i] = '8'; break;
case 'W': case 'X': case 'Y': alphabetic[i] = '9'; break;
default: break;
}
}
printf("%s\n", alphabetic);
return 0;
}
In particular, I enter: COLLECT-800.
It outputs something like this: u░#■   ║k ╩
What did I do wrong?
You have the right idea, but there are two things missing in your program:
Most importantly, the null terminator at the end of the string. After your for loop in which you read the number, add the line:
alphabetic[i] = '\0';
If the user enters lowercase letters, they are ignored in the switch statement. To get around this, include <ctype.h> and change the switch quantity from alphabetic[i] to toupper(alphabetic[i]). Calling toupper on an already upper case letter is benign.
You're not putting a null-terminator anywhere so it's undefined behavior when you read the string regardless of whether you modified it afterwards. Put this line:
alphabetic[num_elements] = 0;
After your for (i = 0; i < MAX_SIZE &&... loop.
Personally, I wouldn't do the getchar loop and instead read in the string like this:
scanf("%49s", alphabetic); // reads in a string up to 50 characters
for (i = 0; alphabetic[i]; i++) { ...

unexpected output from switch statement in c program [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm getting output of a - 0000520 when I input a while i should get 0001010 as per the code I've assigned. Also the default runs every time (tested using a printf statement) for unexplained reason. My code is here:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int splitWord(char* word, int count);
int sunCode(char letter);
int main()
{
char inputString[100];
char splitStrings[10][10];
int i, j, count;
printf("Enter the message.\n");
fgets(inputString, 100, stdin);
j = count = 0;
for (i = 0; i <= (strlen(inputString)); i++) {
if (inputString[i] == ' ' || inputString[i] == '\0') {
splitStrings[count][j] = '\0';
count++;
j = 0;
}
else {
splitStrings[count][j] = inputString[i];
j++;
}
}
printf("\nOriginal String is: %s\n", inputString);
for (i = 0; i < count; i++) {
/*for(j=0;j<=strlen(splitStrings[i]);j++){
printf("%s",splitStrings[i][j]);
}*/
splitWord(splitStrings[i], count);
}
return 0;
}
int splitWord(char* word, int count)
{
int i;
int strLength = strlen(word);
for (i = 0; i <= strLength; i++) {
sunCode(word[i]);
// printf("%c\n",word[i]);
}
return 0;
}
int sunCode(char letter)
{
char letr = tolower(letter);
int code = 0;
switch (letr) {
case '0':
code = 0000000;
break;
case '1':
code = 0000001;
break;
case '2':
code = 0000010;
break;
case '3':
code = 0000011;
break;
case '4':
code = 0000100;
break;
case '5':
code = 0000101;
break;
case '6':
code = 0000110;
break;
case '7':
code = 0000111;
break;
case '8':
code = 0001000;
break;
case '9':
code = 0001001;
break;
case 'a':
code = 0001010;
break;
case 'b':
code = 0001011;
break;
case 'c':
code = 0001100;
break;
case 'd':
code = 0001101;
break;
case 'e':
code = 0001110;
break;
case 'f':
code = 0001111;
break;
case 'g':
code = 0010000;
break;
case 'h':
code = 0010001;
break;
case 'i':
code = 0010010;
break;
case 'j':
code = 0010011;
break;
case 'k':
code = 0010100;
break;
case 'l':
code = 0010101;
break;
case 'm':
code = 0010110;
break;
case 'n':
code = 0010111;
break;
case 'o':
code = 0011000;
break;
case 'p':
code = 0011001;
break;
case 'q':
code = 0011010;
break;
case 'r':
code = 0011011;
break;
case 's':
code = 0011100;
break;
case 't':
code = 0011101;
break;
case 'u':
code = 0011110;
break;
case 'v':
code = 0011111;
break;
case 'w':
code = -010000;
break;
case 'x':
code = 010001;
break;
case 'y':
code = 010010;
break;
case 'z':
code = 010011;
break;
case ' ':
code = 45;
printf("\nis space\n");
break;
default:
break;
}
printf("%c - %07d\n", letr, code);
}
I tried to see if it's giving ASCII values (it isn't)
the letter is being passed properly in the sunCode function (it is)
I do not understand why it is behaving like this, verified the syntax and conditions of switch too.
I am using gcc 7.3.0 on Ubuntu.
Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8.
https://stackoverflow.com/a/1661378/10479742
0001010 in octal is 520 in decimal, and that's why you get that result. Either remove leading zeros, or change code to string.

Nested switch leads to an infinite loop

In the following program, I need to change the initial and final characters to their respective characters as mentioned below in case but this is giving me an infinite loop. What should I do to fix it?
int main(void)
{
char state ='t';
char word[20]="aaabbccaaaaccbbb";
int initiallength = strlen(word)-1; strcat(word,"a");
while(strlen(word)-1 >initiallength)
{
switch(state)
{
case 't':
switch(word[strlen(word)-1])
{
case 'a':
word[strlen(word)-1]='b'; break;
case 'b':
word[strlen(word)-1]='c'; break;
case 'c':
word[strlen(word)-1]='d'; break;
case 'd':
word[strlen(word)-1]='\0'; break;
}
switch(word[0])
{
case 'a':
word[0]='b'; break;
case 'b':
word[0]='c'; break;
case 'c':
word[0]='d'; break;
case 'd':
word[0]='\0'; break;
}
}
}
}
If I understand correctly what you want to do is swap the first and last characters in the given string. If that's the case first your code is way too complicated and second the reason you're getting an infinite loop is because the condition strlen(word)-1 >initiallength is always true.
Test if word is empty
int main(void){
char state ='t';
char word[20]="aaabbccaaaaccbbb";
int initiallength = strlen(word)-1;
strcat(word,"a");
while(strlen(word)-1 >initiallength && strlen(word) >= 0){
printf("%d %d\n", strlen(word)-1, initiallength);
printf("%d len %s\n", strlen(word), word);
switch(state){
case 't':
switch(word[strlen(word)-1]){
case 'a':
case 'b':
case 'c':
word[strlen(word)-1]++;
break;
case 'd':
word[strlen(word)-1] = '\0';
break;
}
switch(word[0]){
case 'a':
case 'b':
case 'c':
word[0]++;
break;
case 'd':
word[0] = '\0';
break;
}
}
}
}

Making a switch statement in C with an array?

I am trying to make a switch statement that takes in a word into an array and then throws each letter through a switch statement and allocates a point to each letter depending on which letter it is and giving a final point value for the word, and I can't seem to get the array part right. Any help would be appreciated!
int main(){
int letter_points = 0;
char word[7];
int word_length = 7;
int i;
printf("Enter a Word\n");
scanf("%s", word);
for(i = 0; i < word_length; i++){
switch(word){
//1 point
case 'A':
case 'E':
case 'I':
case 'L':
case 'N':
case 'O':
case 'R':
case 'S':
case 'T':
case 'U':
letter_points++;
break;
//2 points
case 'D':
case 'G':
letter_points += 2;
break;
//3 points
case 'B':
case 'C':
case 'M':
case 'P':
letter_points += 3;
break;
//4 points
case 'F':
case 'H':
case 'V':
case 'W':
case 'Y':
letter_points += 4;
break;
//5 points
case 'K':
letter_points += 5;
break;
//8 points
case 'J':
case 'X':
letter_points += 8;
break;
//10 points
case 'Q':
case 'Z':
letter_points += 10;
break;
}
}
printf("%d\n", letter_points);
return;
}
It would probably be faster to have a lookup array:
int const letter_score[26] = { 1, 2, 1, 3, ..., 10 };
/* key: A B C D Z */
score += letter_score[c - 'A']; // or "toupper(word[i]) - 'A'"
Caveat: this requires an encoding in which the upper-case letters are arranged contiguously, such as Unicode or ASCII.
Try using this
switch(word[i]){
in the switch statement. As it stands, you are not testing each element in your array even though you are iterating over the range of the array. Having said that I would go for the approach suggested by Kerrek SB in the other answer. This is much neater and more compact.
The variable word is an array, but you want to switch on each character. Thus, you need:
switch(word[i])
In C, you cannot use arrays in switch (and expressions for case). Also, the type passed to switch() and types specified in each case must match. So the most you can do is switch on a character. You almost got it right though, except that you are passing the whole array into switch. Use index to reference a character instead. For example:
switch (word[i]) {
...
}
You have word as an array of size7, you cannot switch on the array, you have to swicth on each character of the array so use:
switch(word[i])

Newbie: After adding cases to a switch in C, it breaks

switch(ch)
{
//input a number
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[g.y][g.x] = ch - '0';
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
// delete an input from the board
case '0':
case KEY_BACKSPACE:
case KEY_DC:
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[y][x] = 0;
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
}
Problem: Case '1' through case '9' worked fine. Then I added case '0', case KEY_BACKSPACE and case KEY_DC. Although it compiles, none of the cases now work, including cases '1' - '9'. What am I missing?
All of your cases are falling through. I assume that you should have a break; before case 0:.
You are missing a break;. In C, switch has fall-through semantics. Once a case is met, all subsequent cases are exceuted unless a break; stops execution.

Resources