Ada I/O: Put_Line not working after Get_Line - console-application

I'm trying to do basic I/O in Ada, but the documentation on this isn't very informative (unless I'm going to the wrong place). In the following block, I was trying to test string appending and output, but for some reason it literally only outputs "Hello WORLD!" I'm sure I'm missing something really simple, but I have been trying for a few hours to figure this out.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
procedure Main is
usrIn : String(1..80);
appendString : Unbounded_String;
last : Natural;
begin
Put_Line ("Hello WORLD!");
Get_Line(usrIn, last);
Put_Line ("AAAAAAAA");
appendString := To_Unbounded_String("USER IN: ");
Append(appendString,usrIn);
Put_Line("Output follows");
Put_Line(To_String(appendString));
end Main;

usrIn is a String(1..80), i.e., an array of 80 characters.
This line:
Append(appendString,usrIn);
appends all 80 characters (most of which are likely garbage) to appendString.
This is what the last argument to Get_Line is for.
Replace userIn by userIn(userIn'First .. last). That's a slice that consists only of the characters read by the Get_Line call.

If you are compiling using a version in Ada 2005 or more, you can also use the function form of Get_Line :
declare
usrIn : constant String := Get_Line;
begin
Append(appendString,usrIn);
end;

Related

What is strlen actually doing?

This is subroutine strlen
subroutine strlen(string,i1,i2)
character string*(*)
do 10 i=len(string),1,-1
if(string(i:i).ne.' ')then
i2=i
goto 11
endif
10 continue
11 do 20 i=1,len(string)
if(string(i:i).ne.' ')then
i1=i
return
endif
20 continue
return
end
In the main
if(nfil.lt.0)then
call strlen(cpar,i1,i2)
open(unit=10,file=cpar(i1:i2),status='old')
If cpar is declared
character cpar*(*)
Does it exist any rule or limitation regarding the name of the cpar to be openned properly?
My hx263on.sens(cpar) can not be read.Why?
The function just looks for the first and the last character which is not a space. These are returned as i1 and i2. cpar(i1:i2) should be the same as adjustl(trim(cpar)) from Fortran 90.
This should not be necessary. Fortran trims file names passed to open anyway. File-names ending with spaces are not supported.
If the file cannot be opened, it probably does not exist or contains some special characters which the operating system does not like. Or it actually contains something else than you think. Maybe the variable is too short or something like that. Verify the value of cpar and cpar(i1:i2) by printing it.

"main.exe" Has Crashed Error

I am having a simple error. The project is to create a skeleton of a basic menu. The new command just counts from 1 to an integer entered by the user. Before I continue, I have posted a link to the pastebin that holds my .cpp file:
http://pastebin.com/pAi9EiEi
The rest of the program runs and works. However, the error is simple. It is crashing as soon as I type in any of the commands. After running error checks, I have found the error is not the while but the if statements. The error is on the lines similar to this:
if (stricmp(strstr(newCommand, cmd2), newCommand) == 0)
What this line is supposed to do, is copy what is in cmd2 and put it in newCommand then comparing it without caps sensitivity to:
char newCommand[] = "new";
"What this line is supposed to do, is copy what is in cmd2 and put it in newCommand then comparing it without caps sensitivity to:"
If the code did this, it would be comparing the former contents of cmd2 to itself, wouldn't it?
copy cmd2 -> newCommand
is cmd2 == newCommand?
If the user typed "open", then on the first iteration of your loop it would copy "open" into "newCommand" and you would no-longer have the string "new" anywhere in your program.
strstr searches the first string for an occurrence of the second.
strstr("hello world", "world"); // returns pointer to 'world' in 'hello world'
strstr("biscuit", "new"); // returns NULL to indicate new doesn't occur in 'biscuit'
Surely what you actually want to do is simply:
if (stricmp(newCommand, cmd2) == 0) {
// match
}
Incidentally, if you did want to copy "cmd2" into "newCommand", you would want to use strcpy(destinationStr, sourceStr);
strcpy(newCommand, cmd2);
that line doesn't do what you think it does
http://www.cplusplus.com/reference/cstring/strstr/
it searches for the occurence of cmd2 in newcommand and returns a pointer to it (null if not found) and unless I'm mistaken passing a null in stricmp is undefined behavior
you just want a plain stricmp and you do away with the copy

getline() omitting the first letter of my output string

Hi i am a newbie in c++ and was doing some basic exercise. my code takes user input and feeds them in an array. Now i am using getline() to get the input string. my code is as follows:
cin.getline(cb[0].name, 200).get(); // Cadburry
cin.getline(cb[1].name, 200).get(); // Snickers
cin.getline(cb[2].name, 200); // Milky Bar
But when i output the strings, the first getline() seems to be fine but the other two are omitting the first letter of the string. So the output in this case is :
Cadburry
nickers
ilky Bar
can anyone please tell me why is it so?
The get() calls are consuming the S and the M, remove those and it will work. getline() already consumes the \n

Simple (mostly) variable parser

In one of my projects, I need to be able to provide a very simple variable find-and-replace parser (mostly for use in paths). Variables are used primarily during startup and occasionally to access files (not the program's primary function, just loading resources), so the parser need not be high-performance. I would greatly prefer it to be thread-safe, however.
The parser needs to be able to store a set of variables (map<string, string> at the moment) and be able to replace tokens with the corresponding value in strings. Variable values may contain other variables, which will be resolved when the variable is used (not when it is added, as variables may be added over time).
The current variable grammar looks something like:
$basepath$/resources/file.txt
/$drive$/$folder$/path/file
My current parser uses a pair of stringstreams ("output" and "varname"), writes to the "output" stream until it finds the first $, the "varname" stream until the second $, then looks up the variable (using the contents of varname.str()). It's very simple and works nicely, even when recursing over variable values.
String Parse(String input)
{
stringstream output, varname;
bool dest = false;
size_t total = input.length();
size_t pos = 0;
while ( pos < total )
{
char inchar = input[pos];
if ( inchar != '$' )
{
if ( dest ) output << inchar;
else varname << inchar;
} else {
// Is a varname start/end
if ( !dest )
{
varname.clear();
dest = true;
} else {
// Is an end
Variable = mVariables.find(varname.str());
output << Parse(Variable.value());
dest = false;
}
}
++pos;
}
return output.str();
}
(error checking and such removed)
However, that method fails me when I try to apply it to my desired grammar. I would like something similar to what Visual Studio uses for project variables:
$(basepath)/resources/file.txt
/$(drive)/$(folder)/path/file
I would also like to be able to do:
$(base$(path))/subdir/file
Recursing in the variable name has run me into a wall, and I'm not sure the best way to proceed.
I have, at the moment, two possible concepts:
Iterate over the input string until I find a $, look for a ( as the next character, then find the matching ) (counting levels in and out until the proper close paran is reached). Send that bit off to be parsed, then use the returned value as the variable name. This seems like it will be messy and cause a lot of copying, however.
The second concept is to use a char *, or perhaps char * &, and move that forward until I reach a terminating null. The parser function can use the pointer in recursive calls to itself while parsing variable names. I'm not sure how best to implement this technique, besides having each call keep track of the name it's parsed out, and append the returned value of any calls it makes.
The project need only compile in VS2010, so STL streams and strings, the supported bits of C++0x, and Microsoft-specific features are all fair game (a generic solution is preferable in case those reqs change, but it's not necessary at this point). Using other libraries is no good, though, especially not Boost.
Both my ideas seem like they're more complicated and messier than is needed, so I'm looking for a nice clean way of handling this. Code, ideas or documents discussing how best to do it are all very much welcome.
Simple solution is to search for the first ')' in the string, then move backwards to see if there's an identifier preceeded by "$(". If so, replace it and restart your scanning. If you don't find "$(" identifier, then find the next ')' - when there isn't one you're finished.
To explain: by searching for a ) you can be sure that you're finding a complete identifier for your substitution, which then has the chance to contribute to some other identifier used in a subsequent substitution.
EXAMPLE
Had a great time on $($(day)$(month)), did you?
Dictionary: "day" -> "1", "month" -> "April", "1April" -> "April Fools Day"
Had a great time on $($(day)$(month)), did you?
^ find this
Had a great time on $($(day)$(month)), did you?
^^^^^^ back up to match this complete substitution
Had a great time on $(1$(month)), did you?
^ substitution made, restart entire process...
Had a great time on $(1$(month)), did you?
^ find this
etc.

lex (flex) generated program not parsing whole input

I have a relatively simple lex/flex file and have been running it with flex's debug flag to make sure it's tokenizing properly. Unfortunately, I'm always running into one of two problems - either the program the flex generates stops just gives up silently after a couple of tokens, or the rule I'm using to recognize characters and strings isn't called and the default rule is called instead.
Can someone point me in the right direction? I've attached my flex file and sample input / output.
Edit: I've found that the generated lexer stops after a specific rule: "cdr". This is more detailed, but also much more confusing. I've posted a shorted modified lex file.
/* lex file*/
%option noyywrap
%option nodefault
%{
enum tokens{
CDR,
CHARACTER,
SET
};
%}
%%
"cdr" { return CDR; }
"set" { return SET; }
[ \t\r\n] /*Nothing*/
[a-zA-Z0-9\\!##$%^&*()\-_+=~`:;"'?<>,\.] { return CHARACTER; }
%%
Sample input:
set c cdra + cdr b + () ;
Complete output from running the input through the generated parser:
--(end of buffer or a NUL)
--accepting rule at line 16 ("set")
--accepting rule at line 18 (" ")
--accepting rule at line 19 ("c")
--accepting rule at line 18 (" ")
--accepting rule at line 15 ("cdr")
Any thoughts? The generated program is giving up after half of the input! (for reference, I'm doing input by redirecting the contents of a file to the generated program).
When generating a lexer that's standalone (that is, not one with tokens that are defined in bison/yacc, you typically write an enum at the top of the file defining your tokens. However, the main loop of a lex program, including the main loop generated by default, looks something like this:
while( token = yylex() ){
...
This is fine, until your lexer matches the rule that appears first in the enum - in this specific case CDR. Since enums by default start at zero, this causes the while loop to end. Renumbering your enum - will solve the issue.
enum tokens{
CDR = 1,
CHARACTER,
SET
};
Short version: when defining tokens by hand for a lexer, start with 1 not 0.
This rule
[-+]?([0-9*\.?[0-9]+|[0-9]+\.)([Ee][-+]?[0-9]+)?
|
seems to be missing a closing bracket just after the first 0-9, I added a | below where I think it should be. I couldn't begin to guess how flex would respond to that.
The rule I usually use for symbol names is [a-zA-Z$_], this is like your unquoted strings
except that I usually allow numbers inside symbols as long as the symbol doesn't start with a number.
[a-zA-Z$_]([a-zA-Z$_]|[0-9])*
A characters is just a short symbol. I don't think it needs to have its own rule, but if it does, then you need to insure that the string rule requires at least 2 characters.
[a-zA-Z$_]([a-zA-Z$_]|[0-9])+