argc/argv problems in c - argv

i'm extremely rusty with C and when trying to compile this i keep getting the error: "lvalue required as left operand of assignment" in each of the three nested ifs.
i'm pretty sure i'm doing some really dumb and basic mistake but i can't manage to fix it!
also the code is extremely naive, is there a better way to check the various strings in argv (they must be 6 charachters long, the first 2 charachters must be either IC, FR or RG and then the other 4 should be a numeric code) and print the correct strings?
int main(int argc, char *argv[]){
int i=1;
while(i < argc){
if(strlen(argv[i]) == 6){
if(argv[i][0] == 'I' && argv[i][1] = 'C' && argv[i][2] >= '0' && argv[i][2] <= '9' && argv[i][3] >= '0' && argv[i][3] <= '9' && argv[i][4] >= '0' && argv[i][4] <= '9' && argv[i][5] >= '0' && argv[i][5] <= '9'){
printf("%s", argv[i]);
}
if(argv[i][0] == 'F' && argv[i][1] = 'R' && argv[i][2] >= 0 && argv[i][2] <= 9 && argv[i][3] >= 0 && argv[i][3] <= 9 && argv[i][4] >= 0 && argv[i][4] <= 9 && argv[i][5] >= 0 && argv[i][5] <= 9){
printf("%s", argv[i]);
}
if(argv[i][0] == 'R' && argv[i][1] = 'G' && argv[i][2] >= 0 && argv[i][2] <= 9 && argv[i][3] >= 0 && argv[i][3] <= 9 && argv[i][4] >= 0 && argv[i][4] <= 9 && argv[i][5] >= 0 && argv[i][5] <= 9){
printf("%s", argv[i]);
}
}
i++;
}
return(0);
}
EDIT: Damn this was a pretty dumb question, wrote = instead of == in the second assignment. thanks for the help!

It's because you have a typo in your second tests in each if, having written = (assignment of a value) instead of == (test for equality).

The error message is correct but not intuitive. The compiler interprets your​ code as follows (note the extra parentheses I inserted):
if ((arg[0] == 'C' && arg[1]) = 'I') {}
This is because && binds more tightly than =. Replace the = with ==, and you're fine.
You should write a helper function:
static bool parse_number(const char *arg, char ch1, char ch2, int *pnum) {
if (arg[0] == ch1 && arg[1] == ch2 && '0' <= arg[2] && arg[2] <= '9') {
char *end;
unsigned long num = strtoul(arg + 2, &end, 10);
if (*end == '\0' && end - arg == 6) {
*pnum = (int)num;
return true;
}
}
return false;
}
Then you can use it like this:
int num;
if (parse_number(argv[i], 'I', 'C', &num)) {
printf("IC number %d\n", num);
}

Related

cs50 mario less problem - my code is printing in a single line. I cant find whats wrong with it

#include <cs50.h>
#include <stdio.h>
int main(void)
{
int n;
do
{
n = get_int("Height: ");
}
while ((n < 1) || (n > 8));
for
(int i = 0; i < n; i++)
{for (int j = 0; j < n; j++)
if(i+j < n-1)
printf(" ");
else
printf("#");
}
printf("\n");
}
Make sure you use {} to enclose codes blocks for every for loop and if conditional. This printf("\n"); is outside both for blocks and thus prints exactly once. (The closing brace } before the final printf closes the code block of the i loop).
Your code is formatted poorly which makes it hard for yourself:
#include <cs50.h>
#include <stdio.h>
int main(void) {
int n;
do {
n = get_int("Height: ");
} while ((n < 1) || (n > 8));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
if(i + j < n - 1)
printf(" ");
else
printf("#");
}
printf("\n");
}
So you run you loops then print a single newline. It's not clear if you want:
newline after each " " and "#":
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
printf("%c\n", i + j < n - 1 ? ' ' : '#');
newline for each 'i':
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%c", i + j < n - 1 ? ' ' : '#');
printf("\n");
}

How can I reverse print the characters of a string in each cell using AWK?

Beth 45 4.00 0 0 .072
Danny 33 3.75 ^0 0 .089
The above is the file I want to operate.
I want to write an AWK script that can reverse print the characters of a string in every cell.
Here is the code:
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i) ;
print;
}
END {}
However, it does not work. The program somehow becomes dead.
I have found if I don't use the loop and handle each field one by one like the following,
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
$1 = reverse_print($1) ;
$2 = reverse_print($2) ;
$3 = reverse_print($3) ;
$4 = reverse_print($4) ;
$5 = reverse_print($5) ;
$6 = reverse_print($6) ;
print;
}
END {}
it can work well.
Here is my desired output:
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
I have thought hard but still cannot figure out where I did wrong using the loop.
Who can tell me why ?
You're using the same variable i inside and outside of the function. Use a different variable in either location or change the function definition to reverse_print(str, i) to make the i used within the function local to that function rather than the same global variable being used in the calling code.
You should also make s and N function local:
function reverse_print(str, i, s, N)
but in fact the code should be written as:
$ cat tst.awk
BEGIN { OFS = "\t\t" }
function reverse_print(fwd, rev, i, n)
{
n = length(fwd)
for (i = n; i >= 1; i--)
rev = rev substr(fwd, i, 1);
return rev
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i)
print
}
$ awk -f tst.awk file
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
Could you please try following.(This program is tested on GNU awk only and as per Ed sir's comment too this is undefined behavior for POSIX awk)
awk '
BEGIN{
OFS="\t\t"
}
{
for(i=1;i<=NF;i++){
num=split($i,array,"")
for(j=num;j>0;j--){
val=(j<num?val:"") array[j]
}
printf "%s%s",val,(i<NF?OFS:ORS)}
val=""
}' Input_file
There is a rev command in Linux: rev - reverse lines characterwise.
You can reverse a string by calling rev with awk builtin function system like:
#reverse-fields.awk
{
for (i = 1; i <= NF; i = i + 1) {
# command line
cmd = "echo '" $i "' | rev"
# read output into revfield
cmd | getline revfield
# remove leading new line
a = gensub(/^[\n\r]+/, "", "1", revfield)
# print reversed field
printf("%s", a)
# print tab
if (i != NF) printf("\t")
# close command
close(cmd)
}
# print new line
print ""
}
$ awk -f reverse-fields.awk emp.data
0 00.4 hteB
0 57.3 naD
01 00.4 yhtaK
02 00.5 kraM
22 05.5 yraM
81 52.4 eisuS

Read all the entries of a matrix using shell script

I have a matrix,
A(i,j), i=1,m and j=1,n
I can read it in C and FORTRAN, but I can't read it in shell script. I know this is a very simple question, but I am very new to shell script. I want to read all entries and do some calculation e.g. I have a matrix:
A= 1 0 1 1
2 1 0 2
1 0 0 3
1 2 3 0
Now I want to compare each 0 with its above, below, left and right values. Finally I want to do some computation (lets say sum) with these four values around each zero. In the above example the result will be- for five zeros
1st zero: 3
2nd zero: 4
3rd zero: 4
4th zero: 6
5th zero: 6
So in FORTRAN, I can do it by reading all the values as
do j=1,n
do i=1,m
if (A(i,j) .eq. 0) then
B(i,j)=A(i-1,j)+A(i+1,j)+A(i,j+1)+A(i,j-1)
enddo
enddo
But I want to do it in shell script. How to do?
Assuming that data are given in "test.dat" (with no "A = "), I tried it anyway...
#!/bin/bash
inpfile="test.dat"
L=100 # some large value
for (( i = 0; i < L; i++ )) {
for (( j = 0; j < L; j++ )) {
A[ L * i + j ]=0
}
}
i=1
while read buf; do
inp=( $buf ); n=${#inp[#]}
if (( L <= n+1 )); then echo "L is too small"; exit -1; fi
for (( j = 1; j <= n; j++ )) {
A[ L * i + j ]=${inp[j-1]}
}
(( i++ ))
done < $inpfile
nzeros=0
for (( i = 1; i <= n; i++ )) {
for (( j = 1; j <= n; j++ )) {
if (( ${A[ L * i + j ]} == 0 )); then
(( nzeros++ ))
B[ nzeros ]=$(( \
${A[ L * (i-1) + j ]} + \
${A[ L * (i+1) + j ]} + \
${A[ L * i + j+1 ]} + \
${A[ L * i + j-1 ]} ))
fi
}
}
for (( k = 1; k <= nzeros; k++ )) {
printf "%dst zero: %d\n" $k ${B[k]}
}
Conclusion: Very painful. Fortran is recommended...(as expected)

Counting Vowels using a For Loop

Hey guys I haven't been able to find the proper guidance on this specific Vowel counting program so any help would be appreciated.
This is my code so far, I'm not entirely sure where the error lies (probably in the for loop since I'm pretty green with them). The vowelCount variable is not counting properly either.
Thanks in advance.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main() {
char letter(10);
int vowelCount(0);
cout << "Enter a maximum of 10 characters: ";
cin >> letter;
for (int i = 0; i <= letter; i++) {
if (letter == 'a' || letter == 'A' ||
letter == 'e' || letter == 'E' ||
letter == 'i' || letter == 'I' ||
letter == 'o' || letter == 'O' ||
letter == 'u' || letter == 'U') {
vowelCount++;
}
}
cout << "\nTotal number of vowels: " << vowelCount;
cout << endl;
return 0;
}
There are a few mistakes with your code:
char letter(10) is not an array of char, but a single char.
Your for loop goes to the letter value (which is 10, granted) but will not be once you fix letter to be an array.
Also, when you read the variable letter, you should use the operator[] to access its elements.
The following is the correct code:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
char letter;
int vowelCount(0);
cout << "Enter a maximum of 10 characters: ";
for (int i = 0; i < 10; i++)
{
cin >> letter;
if (letter == 'a' || letter == 'A' ||
letter == 'e' || letter == 'E' ||
letter == 'i' || letter == 'I' ||
letter == 'o' || letter == 'O' ||
letter == 'u' || letter == 'U')
{
vowelCount++;
}
}
cout << "\nTotal number of vowels: " << vowelCount;
cout << endl;
return 0;
}
The problem is that you declare a single character (and initialize to 10), that you read into. Then you loop from zero to the ASCII value of that letter. You should either read into a string or an array of characters.
If you go for the latter (array of characters) remember that in C++ such strings need one extra character (to terminate the string). So if you want a string of 10 characters, you have to declare the array to be 11 characters big.

Handling error in function in Haskell

I have a sign function, which can return an error.
signe :: Int -> Char
signe chiffre
| chiffre >= 1 && chiffre <= 9 = '+'
| chiffre == 0 = '0'
| chiffre >= -9 && chiffre <= (-1) = '-'
| otherwise = error "Erreur in the sign"
I'd like to make a simple one to return the corresponding code of the sign, but with error handling.
signes liste = [ signe x | x<-liste ]
I give you an example : For now, if I call
signes [1,3,0,-10]
it gives me
++0*** Exception: Error in sign.
I'd like to have nothing instead of Exception: ++0.
You can, and should, use Maybe in such cases:
signe chiffre
| chiffre >= 1 && chiffre <= 9 = Just '+'
....
| otherwise = Nothing -- parbleu!!
signes = mapMaybe signe
You may need to import Data.Maybe for the mapMaybe function.
A better way would be to actually use the Maybe type which lets you literally return Nothing or Just aValue. You could rewrite your function as
signe :: Int -> Maybe Char
signe chiffre
| chiffre >= 1 && chiffre <= 9 = Just '+'
| chiffre == 0 = Just '0'
| chiffre >= (-9) && chiffre <= (-1) = Just '-'
| otherwise = Nothing
The problem already seems to be answered by Ingo, but I wanted to point out that since you had an error message in the original question, perhaps "Either" would be a better choice here
signe :: Int -> Either String Char
signe chiffre
| chiffre >= 1 && chiffre <= 9 = Right'+'
| chiffre == 0 = Right '0'
| chiffre >= -9 && chiffre <= (-1) = Right '-'
| otherwise = Left "Erreur in the sign"
where you can get the filtered list with
signes liste = [ x | Right x<-map signe liste ]
Both Maybe and Either are used for error checking, Either gives you the ability to pass an "Exception" up the call chain.

Resources