Lab 04: Strings and Command Line Arugments
Table of Contents
Preliminaries
Lab Learning Goals
- Write programs that manipulate C strings
- Perform basic pointer manipulation and arithemetic
- Process command line arguments
- Convert between strings and other data types
- Implement simple algorithm as described in pseudocode
Lab Setup
Run the following command
~aviv/bin/ic221-up
Change into the lab directory
cd ~/ic221/labs/04
All the material you need to complete the lab can be found in the lab directory. All material you will submit, you should place within the lab directory. Throughout this lab, we refer to the lab directory, which you should interpret as the above path.
Submission Folder
For this lab, all programs should be placed in the following folder:
~/ic221/labs/04
Only programs found in the folder will be graded.
Submission Instructions
To submit, make sure that all your programs are in the submission folder on a Computer Science department lab machine, i.e., a machine in MI301. Then issue the command:
~aviv/bin/ic221-submit
Follow the prompts and select the right submission to submit.
Common Mistakes:
- You are not logged into a lab machine and are instead on your local machine. Solution: ssh into a lab machine and run the submit script.
- You did not copy your code from your local machine to a lab machine. Solution: use sshfs to mount your account and submit your code, or use scp to copy your code.
If you still have trouble submitting your code, email your instructor.
Test Script
To help you complete the lab, I have provide a test script that will run basic tests against your program. The script is not designed to be comprehensive, and you will graded based on a larger array of tests. To execute the test script, run it from anywhere within the lab directory.
./test.sh
Working Example
To help you, I have a working example of the lab located in my home directory at:
~aviv/ic221-examples/palendrome ~aviv/ic221-examples/creditcheck
You can run it with your own input to test your program.
README file
You are required to submit and complet the README file in your submission folder. Please answer all questions and filel in any comments there.
Compiling your code:
To compile your code, use gcc
the gnu c compiler using the
following command:
gcc -Wall -g manipulator.c -o manipulator
The -Wall
option will provide additional warnings. The -g
option will include debugging symbols in case you want to use the
debugger.
Part 1: String Manipulation (30 Points)
For this part of the lab, you will complete a small program to check if the input provided by the user is a palindrome. A palindrome is a string that is the same forward and backwards.
There are two main ways for testing if a string is a palindrome:
- Iterate from forward to back, and from back to forward, and check that they are the same.
- Create a copy of the string, in reverse, and check that the copy matches the original.
You will implement both; however, the challenge is working with C strings. The main portion of the program, provided to you, looks like such:
int main(int argc, char * argv[]){ char str[1024]; printf("Enter a string:\n"); scanf("%1023s",str); if(check1(str)){ printf("Palindrome according to check 1\n"); }else{ printf("NOT a palindrome according to check 1\n"); } if(check2(str)){ printf("Palindrome according to check 2\n"); }else{ printf("NOT a palindrome according to check 2\n"); } }
Note that the input is read into the str
string and may be
substantially shorter then the length 1024. It is also passed to the
check1()
and check2()
functions without a length argument. You
should make sure that you use strlen()
somewhere.
Additionally, to complete check2()
which requires making a copy of
the string; don't forget that C strings must be NULL terminated. If
you do not NULL terminate, strcmp()
will not work.
- You must complete the
palindrome
program using two checks. check1()
andcheck2()
must use two distinct algorithms:check1()
use to iterators, one from the start and one from the end of the string, to check if the front and back are the samecheck2()
copy the string to a new string, in reverse, and compare the two strings usingstrcmp()
- (Extra Credit: 5 points): Complete both
check1()
andcheck2()
algorithms only using pointer types, no integers. That is, you may not us integer indexing of the string like so:str[i]
. If you complete the extra credit, be sure to indicate so in your README file.
Here is some sample output:
aviv@saddleback: part1 $ ./palendrome
Enter a string:
racecar
Palendrone according to check 1
Palendrone according to check 2
aviv@saddleback: part1 $ ./palendrome
Enter a string:
madamimadam
Palendrone according to check 1
Palendrone according to check 2
aviv@saddleback: part1 $ ./palendrome
Enter a string:
amanaplanacanalpanama
Palendrone according to check 1
Palendrone according to check 2
aviv@saddleback: part1 $ ./palendrome
Enter a string:
notapalendrome
NOT a palendrone according to check 1
NOT a palendrone according to check 2
aviv@saddleback: part1 $
Part 2: Credit Card Checking with Luhn's Algorithm (70 points)
For this part of the lab, you will implement a checksum for credit card numbers. A checksum is a method to verify that a number meets certain properties. It is an important principle in networking and other areas, and you will implement the checksum used to check if a credit card is valid. Note that just because a number passes the checksum, it doesn't make it a truly valid credit card number, it just means that it may be used as a credit card number.
Credit card numbers are checked using Luhn's Algorithm. You can find a description on wikipedia, but it is highlighted below. It occurs in three basic steps:
- For the 16 digit phone number, double ever other digit
6 4 7 4 5 6 2 3 8 9 9 7 2 7 5 6 <- number | | | | | | | | v v v v v v v v 12 14 10 4 16 18 4 10 <- double every other digit
- If the double of the digit is greater than 9, that is two digits in length, replace it with the sum of the digits of the product
6 4 7 4 5 6 2 3 8 9 9 7 2 7 5 6 <- number | | | | | | | | | | | | | | | | v | v | v | v | v | v | v | v | 12 | 14 | 10 | 4 | 16 | 18 | 4 | 10 | | | | | | | | | | | | | | | | | v v v v v v v v v v v v v v v v 3 4 5 4 1 6 4 3 7 9 9 7 4 7 1 6 <- sume of digits if >9
- Take the sume of the remaining numbers
3 + 4 + 5 + 4 + 1 + 6 + 4 + 3 + 7 + 9 + 9 + 7 + 4 + 7 + 1 + 6 = 80
- If that number is a multiple of 10, then it passes the checksum.
80%10 = 0 <- PASS
For your program to work, you must take a 16 digit credit card number on the command line and print VALID or INVALID. Like so:
aviv@saddleback: part2 $ ./creditcardcheck 6474562389972756 VALID aviv@saddleback: part2 $ ./creditcardcheck 6474562389972757 INVALID
Additionally, your program should detect three error conditions: (1) No argument provided; (2) Invalid length of credit card number; (3) Invalid numbers in credit card. Here's an example:
aviv@saddleback: part2 $ ./creditcardcheck ERROR: require credit card number aviv@saddleback: part2 $ ./creditcardcheck 12345 ERROR: Invalid credit card number: Bad Length aviv@saddleback: part2 $ ./creditcardcheck 12345a7890123456 ERROR: Invalid credit card number: Bad number 'a'
To perform these checks, consider that the command line arguments are a string, and each number is currently a character. The numeric value of that character is not the same as its integer value, but they are still ordered. For example, this will check for a valid digit:
if ( c >= '0' && c <= '9' ) printf("Valid digit!\n"); else printf("Invalid digit!\n");
Finally, because the checksum occurs over integers and not strings, you will need to convert each individual digit into a integer. Consider creating an array for the credit card number that can store all these digits:
int ccnum[16]
You can use atoi()
to perform the conversation from string to
integer, but you'll need to first isolate the character of the number
as its own string.
char num[2]; num[0] = '8'; num[1] = '\0'; //null terminate int i = atoi(num); //convert to integer
- You must complete the
creditcardcheck
- Your program must print "VALID" for a valid credit card number that passes Luhn's checksum and "INVALID" for a credit card number that does not pass the checksum
- You must take the credit card number as the command line argument
and check for the following the errors and print the following
error statements:
- No argument provided: "ERROR: require credit card number" printed to
stderr
- Credit card is not the right length: "ERROR: Invalid credit card number: Bad Length" printed to
stderr
- A non-digit appears in the number: "ERROR: Invalid credit card
number: Bad number '%c'" (the "%c" should be formatted to the
invalid character) print to
stderr
- No argument provided: "ERROR: require credit card number" printed to
- Your program should also return the following codes for exit values:
return 0
: valid credit card numberreturn 1
: errorreturn 2
: invlalid credit card number
- (Extra Credit: 5 points): Write a bash script
rand_creditcard.sh
that will find a random, valid credit card number by using thecreditcardcheck
program. You may write any additional programs to complete this tasks, such as one to create a random credit card, but your program must perform exactly as below:aviv@saddleback: part2 $ ./rand_creditcard.sh 1002947242955100 aviv@saddleback: part2 $ ./rand_creditcard.sh 8113723297573564
Here is some sample output of creditcardcheck
:
aviv@saddleback: part2 $ ./creditcardcheck 6474562389972756
VALID
aviv@saddleback: part2 $ ./creditcardcheck 6474562389972757
INVALID
aviv@saddleback: part2 $ ./creditcardcheck
ERROR: require credit card number
aviv@saddleback: part2 $ ./creditcardcheck 12345
ERROR: Invalid credit card number: Bad Length
aviv@saddleback: part2 $ ./creditcardcheck 12345a7890123456
ERROR: Invalid credit card number: Bad number 'a'