I am building a script that is embedded in HTML to generate a report that extracts information from an internal company system.
The objective is to build some kind of a funnel, making the sum of records in each of the stages. For example, I have:
Processes in stage 1 = "3"
Processes in stage 2 = "5"
Processes in stage 3 = " "
Processes at stage 4 = "2"
Processes in stage 5 = " "
However, I have a problem when one of the stages is empty (it is not 0) because there is no stage in that specific process. When I try to add, for example, Stage 1 and Stage 3, it always returns an empty value, while it should give result 3 (3 + 0).
<p id="global_calc"></p>
<script>
{
var A = Stage1.system.count;
var B = Stage2.system.count;
var total = A + B;
}
document.getElementById("global_calc").innerHTML = "The total of this stage is: " + total;
</script>
The Stage.system.count is the internal system's variable that has the number I want to eventually sum with var total.
But, for example, if Stage1.system.count = 3 and Stage2.system.count = " ", total result in " " instead of 3. How can I make this to count the black space as a 0?
First it's probably worth checking what variables you have; any number + " " will always give you a string:
const x = 123 + " "; // "123 ";
const y = 123 + "" // "123"
We can see that in practice in your example:
{
var A = 3;
var B = " ";
var total = A + B;
}
document.getElementById("global_calc").innerHTML = "The total of this stage is: " + total;
console.log(("The total of this stage is: " + total).replace(/ /g, '*'))
<div id="global_calc"></div>
It seems like you're using undefined as part of the addition, which returns the value NaN:
{
var A = 3;
var B = undefined;
var total = A + B;
}
document.getElementById("global_calc").innerHTML = "The total of this stage is: " + total;
console.log(("The total of this stage is: " + total).replace(/ /g, '*'))
<div id="global_calc"></div>
We'll need more details to figure out exactly why you're getting " " for total.
If you want a function which converts number -> number and " " -> 0 then Number would do:
const x = 3;
const y = " ";
console.log(Number(x));
console.log(Number(y));
I'm new to Javascript and I'm curious as to how to store values in a string and then return it. In the example below 2 numbers are picked, for example 2 and 8, and the program should return 2x1 =2, 2x2=4,..... all the way up to 2x8 =16. This can obviously be done by constantly looping a print statement as I have done, but how would I be able to store all the values in a String and then return the string.
function showMultiples (num, numMultiples)
{
for (i = 1; i < numMultiples; i++)
{
var result = num*i;
console.log(num + " x " + i + " = " + result+ "\n");
}
}
console.log('showMultiples(2,8) returns: ' + showMultiples(2,8));
console.log('showMultiples(3,2) returns: ' + showMultiples(3,2));
console.log('showMultiples(5,4) returns: ' + showMultiples(5,4));
function showMultiples(num, numMultiples) {
// the accumulator (should be initialized to empty string)
var str = "";
for (i = 1; i < numMultiples; i++) {
var result = num * i;
// use += to append to str instead of overriding it
str += num + " x " + i + " = " + result + "\n";
}
// return the result str
return str;
}
var mulOf5 = showMultiples(5, 10);
console.log("multiples of 5 are:\n" + mulOf5);
The operator += add the a value (right operand) to the previous value of the left operand and stores the result in the later. So these two lines are the same:
str = str + someValue;
str += someValue;
You could just use string concatenation:
var finalResult = ""
...in your loop...
finalResult += num + " x " + i + " = " + result+ "\n"
Often you can also just collect the results in an array and use join to append them.
var lines = [];
... in your loop:
lines.push(num + " x " + i + " = " + result);
... afterwards
console.log(lines.join("\n"));
In case you wanted to use ES6 syntax using backticks for a template string, you can use the below. This is a little more readable and is exactly where it is useful (so long as you can use ES6 wherever you're using JavaScript).
function showMultiples(num, numMultiples){
let result = '';
for(let i = 1; i < numMultiples; i++){
result += `${num} x ${i} = ${i * num}\n`;
};
return result;
}
console.log(showMultiples(2,8));
I'm trying to find a way to "pretty print" a JavaScript data structure in a human-readable form for debugging.
I have a rather big and complicated data structure being stored in JS and I need to write some code to manipulate it. In order to work out what I'm doing and where I'm going wrong, what I really need is to be able to see the data structure in its entirety, and update it whenever I make changes through the UI.
All of this stuff I can handle myself, apart from finding a nice way to dump a JavaScript data structure to a human-readable string. JSON would do, but it really needs to be nicely formatted and indented. I'd usually use Firebug's excellent DOM dumping stuff for this, but I really need to be able to see the entire structure at once, which doesn't seem to be possible in Firebug.
Use Crockford's JSON.stringify like this:
var myArray = ['e', {pluribus: 'unum'}];
var text = JSON.stringify(myArray, null, '\t'); //you can specify a number instead of '\t' and that many spaces will be used for indentation...
Variable text would look like this:
[
"e",
{
"pluribus": "unum"
}
]
By the way, this requires nothing more than that JS file - it will work with any library, etc.
I wrote a function to dump a JS object in a readable form, although the output isn't indented, but it shouldn't be too hard to add that: I made this function from one I made for Lua (which is much more complex) which handled this indentation issue.
Here is the "simple" version:
function DumpObject(obj)
{
var od = new Object;
var result = "";
var len = 0;
for (var property in obj)
{
var value = obj[property];
if (typeof value == 'string')
value = "'" + value + "'";
else if (typeof value == 'object')
{
if (value instanceof Array)
{
value = "[ " + value + " ]";
}
else
{
var ood = DumpObject(value);
value = "{ " + ood.dump + " }";
}
}
result += "'" + property + "' : " + value + ", ";
len++;
}
od.dump = result.replace(/, $/, "");
od.len = len;
return od;
}
I will look at improving it a bit.
Note 1: To use it, do od = DumpObject(something) and use od.dump. Convoluted because I wanted the len value too (number of items) for another purpose. It is trivial to make the function return only the string.
Note 2: it doesn't handle loops in references.
EDIT
I made the indented version.
function DumpObjectIndented(obj, indent)
{
var result = "";
if (indent == null) indent = "";
for (var property in obj)
{
var value = obj[property];
if (typeof value == 'string')
value = "'" + value + "'";
else if (typeof value == 'object')
{
if (value instanceof Array)
{
// Just let JS convert the Array to a string!
value = "[ " + value + " ]";
}
else
{
// Recursive dump
// (replace " " by "\t" or something else if you prefer)
var od = DumpObjectIndented(value, indent + " ");
// If you like { on the same line as the key
//value = "{\n" + od + "\n" + indent + "}";
// If you prefer { and } to be aligned
value = "\n" + indent + "{\n" + od + "\n" + indent + "}";
}
}
result += indent + "'" + property + "' : " + value + ",\n";
}
return result.replace(/,\n$/, "");
}
Choose your indentation on the line with the recursive call, and you brace style by switching the commented line after this one.
... I see you whipped up your own version, which is good. Visitors will have a choice.
You can use the following
<pre id="dump"></pre>
<script>
var dump = JSON.stringify(sampleJsonObject, null, 4);
$('#dump').html(dump)
</script>
In Firebug, if you just console.debug ("%o", my_object) you can click on it in the console and enter an interactive object explorer. It shows the entire object, and lets you expand nested objects.
For Node.js, use:
util.inspect(object, [options]);
API Documentation
For those looking for an awesome way to see your object, check prettyPrint.js
Creates a table with configurable view options to be printed somewhere on your doc. Better to look than in the console.
var tbl = prettyPrint( myObject, { /* options such as maxDepth, etc. */ });
document.body.appendChild(tbl);
I'm programming in Rhino and I wasn't satisfied with any of the answers that were posted here. So I've written my own pretty printer:
function pp(object, depth, embedded) {
typeof(depth) == "number" || (depth = 0)
typeof(embedded) == "boolean" || (embedded = false)
var newline = false
var spacer = function(depth) { var spaces = ""; for (var i=0;i<depth;i++) { spaces += " "}; return spaces }
var pretty = ""
if ( typeof(object) == "undefined" ) { pretty += "undefined" }
else if ( typeof(object) == "boolean" ||
typeof(object) == "number" ) { pretty += object.toString() }
else if ( typeof(object) == "string" ) { pretty += "\"" + object + "\"" }
else if ( object == null) { pretty += "null" }
else if ( object instanceof(Array) ) {
if ( object.length > 0 ) {
if (embedded) { newline = true }
var content = ""
for each (var item in object) { content += pp(item, depth+1) + ",\n" + spacer(depth+1) }
content = content.replace(/,\n\s*$/, "").replace(/^\s*/,"")
pretty += "[ " + content + "\n" + spacer(depth) + "]"
} else { pretty += "[]" }
}
else if (typeof(object) == "object") {
if ( Object.keys(object).length > 0 ){
if (embedded) { newline = true }
var content = ""
for (var key in object) {
content += spacer(depth + 1) + key.toString() + ": " + pp(object[key], depth+2, true) + ",\n"
}
content = content.replace(/,\n\s*$/, "").replace(/^\s*/,"")
pretty += "{ " + content + "\n" + spacer(depth) + "}"
} else { pretty += "{}"}
}
else { pretty += object.toString() }
return ((newline ? "\n" + spacer(depth) : "") + pretty)
}
The output looks like this:
js> pp({foo:"bar", baz: 1})
{ foo: "bar",
baz: 1
}
js> var taco
js> pp({foo:"bar", baz: [1,"taco",{"blarg": "moo", "mine": "craft"}, null, taco, {}], bleep: {a:null, b:taco, c: []}})
{ foo: "bar",
baz:
[ 1,
"taco",
{ blarg: "moo",
mine: "craft"
},
null,
undefined,
{}
],
bleep:
{ a: null,
b: undefined,
c: []
}
}
I've also posted it as a Gist here for whatever future changes may be required.
jsDump
jsDump.parse([
window,
document,
{ a : 5, '1' : 'foo' },
/^[ab]+$/g,
new RegExp('x(.*?)z','ig'),
alert,
function fn( x, y, z ){
return x + y;
},
true,
undefined,
null,
new Date(),
document.body,
document.getElementById('links')
])
becomes
[
[Window],
[Document],
{
"1": "foo",
"a": 5
},
/^[ab]+$/g,
/x(.*?)z/gi,
function alert( a ){
[code]
},
function fn( a, b, c ){
[code]
},
true,
undefined,
null,
"Fri Feb 19 2010 00:49:45 GMT+0300 (MSK)",
<body id="body" class="node"></body>,
<div id="links">
]
QUnit (Unit-testing framework used by jQuery) using slightly patched version of jsDump.
JSON.stringify() is not best choice on some cases.
JSON.stringify({f:function(){}}) // "{}"
JSON.stringify(document.body) // TypeError: Converting circular structure to JSON
Taking PhiLho's lead (thanks very much :)), I ended up writing my own as I couldn't quite get his to do what I wanted. It's pretty rough and ready, but it does the job I need. Thank you all for the excellent suggestions.
It's not brilliant code, I know, but for what it's worth, here it is. Someone might find it useful:
// Usage: dump(object)
function dump(object, pad){
var indent = '\t'
if (!pad) pad = ''
var out = ''
if (object.constructor == Array){
out += '[\n'
for (var i=0; i<object.length; i++){
out += pad + indent + dump(object[i], pad + indent) + '\n'
}
out += pad + ']'
}else if (object.constructor == Object){
out += '{\n'
for (var i in object){
out += pad + indent + i + ': ' + dump(object[i], pad + indent) + '\n'
}
out += pad + '}'
}else{
out += object
}
return out
}
For anyone checking this question out in 2021 or post-2021
Check out this Other StackOverflow Answer by hassan
TLDR:
JSON.stringify(data,null,2)
here the third parameter is the tab/spaces
This is really just a comment on Jason Bunting's "Use Crockford's JSON.stringify", but I wasn't able to add a comment to that answer.
As noted in the comments, JSON.stringify doesn't play well with the Prototype (www.prototypejs.org) library. However, it is fairly easy to make them play well together by temporarily removing the Array.prototype.toJSON method that prototype adds, run Crockford's stringify(), then put it back like this:
var temp = Array.prototype.toJSON;
delete Array.prototype.toJSON;
$('result').value += JSON.stringify(profile_base, null, 2);
Array.prototype.toJSON = temp;
I thought J. Buntings response on using JSON.stringify was good as well. A an aside, you can use JSON.stringify via YUIs JSON object if you happen to be using YUI. In my case I needed to dump to HTML so it was easier to just tweak/cut/paste PhiLho response.
function dumpObject(obj, indent)
{
var CR = "<br />", SPC = " ", result = "";
if (indent == null) indent = "";
for (var property in obj)
{
var value = obj[property];
if (typeof value == 'string')
{
value = "'" + value + "'";
}
else if (typeof value == 'object')
{
if (value instanceof Array)
{
// Just let JS convert the Array to a string!
value = "[ " + value + " ]";
}
else
{
var od = dumpObject(value, indent + SPC);
value = CR + indent + "{" + CR + od + CR + indent + "}";
}
}
result += indent + "'" + property + "' : " + value + "," + CR;
}
return result;
}
Lots of people writing code in this thread, with many comments about various gotchas. I liked this solution because it seemed complete and was a single file with no dependencies.
browser
nodejs
It worked "out of the box" and has both node and browser versions (presumably just different wrappers but I didn't dig to confirm).
The library also supports pretty printing XML, SQL and CSS, but I haven't tried those features.
A simple one for printing the elements as strings:
var s = "";
var len = array.length;
var lenMinus1 = len - 1
for (var i = 0; i < len; i++) {
s += array[i];
if(i < lenMinus1) {
s += ", ";
}
}
alert(s);
My NeatJSON library has both Ruby and JavaScript versions. It is freely available under a (permissive) MIT License. You can view an online demo/converter at:
http://phrogz.net/JS/neatjson/neatjson.html
Some features (all optional):
Wrap to a specific width; if an object or array can fit on the line, it is kept on one line.
Align the colons for all keys in an object.
Sort the keys to an object alphabetically.
Format floating point numbers to a specific number of decimals.
When wrapping, use a 'short' version that puts the open/close brackets for arrays and objects on the same line as the first/last value.
Control the whitespace for arrays and objects in a granular manner (inside brackets, before/after colons and commas).
Works in the web browser and as a Node.js module.
flexjson includes a prettyPrint() function that might give you what you want.
I was asked to convert some VB6/VBScript code to javascript so after googling it and not finding anything I can use,I wrote a small javascript function to help me do the conversion; it's so crude and only converts (some of) the synatx, but it worked for me for the job I had...now I'm thinking of improving it but the method I used is so primitive (Regular Expression matching and replacing).
So...my question is:
What is the proper way to parse source code? is there any (not so complicated) way of doing it? and I don't want to use Exe's, it must be done entirely in Javascript. I'm not searching for ready-to-use source code (I don't think it exists!) but I want to learn how to be able to start with source code and turn it into objects (the opposite of serialization, I think?).
//here is the code:
var strs=[];
function vbsTojs(vbs){
var s = vbs;
s = HideStrings(s);
//only function block
s = s.match(/Function[\w\W]+End\s+Function/gim)[0];
//line-continuation char
s = s.replace(/_\n/gm,"");
//replace ":" with CRLF
s = s.replace(/:/gm,"\n");
//move inline comment to its own line
s = s.replace(/^(.+)'(.*)$/gim,"'$2\n$1");
//single line if -> multiple line
s = s.replace(/\bthen\b[ \t](.+)/gi,"then\n$1\nEnd If");
//alert(s);
var Vars='';
var Fx='';
var FxHead='';
var Args = '';
a=s.split('\n');
//trim
for(i=0;i<a.length;i++){
a[i]=a[i].replace(/^\s+|\s+$/,"");
}
//remove empty items
a=a.filter(function(val) { return val !== ""; });
//alert(a.join('\n'));
//function
a[0]=a[0].replace(/function\s+/i,"");
Fx = a[0].match(/^\w+/)[0];
a[0]=a[0].replace(Fx,"").replace(/[\(\)]/g,"");
a[0]=a[0].replace(/\bbyval\b/gi,"").replace(/\bbyref\b/gi,"").replace(/\boptional\b/gi,"");
a[0]=a[0].replace(/\bas\s+\w+\b/gi,"");
a[0]=a[0].replace(/\s+/g,"");
a[0]=a[0].replace(/,/gi,", ");
FxHead = "function " + Fx+ " ("+ a[0] + "){";
a[0]="";
//end function
a.length = a.length-1;
for(i=1;i<a.length;i++){
//Vars
if(a[i].search(/^dim\s+/i)>-1){
a[i]=a[i].replace(/dim\s*/i,"");
Vars += a[i] + ",";
a[i]='';
//FOR
}else if(a[i].search(/^\bFOR\b\s+/i)>-1){
a[i]=a[i].replace(/^\bFOR\b\s+/i,"");
counter = a[i].match(/^\w+/)[0];
from = a[i].match(/=\s*[\w\(\)]+/)[0];
from=from.replace(/=/,"").replace(/\s+/g,"");
a[i]=a[i].replace(counter,"").replace(from,"").replace(/\bTO\b/i,"");
to = a[i].match(/\s*[\w\(\)]+\s*/)[0];
to=to.replace(/=/,"").replace(/\s+/g,"");
a[i] = "for(" + counter + "=" + from + "; " + counter + "<=" + to + "; " + counter + "++){"
//NEXT
}else if(a[i].search(/^NEXT\b/i)>-1){
a[i] = "}";
//EXIT FOR
}else if(a[i].search(/\bEXIT\b\s*\bFOR\b/i)>-1){
a[i] = "break";
//IF
}else if(a[i].search(/^\bIF\b\s+/i)>-1){
a[i]=a[i].replace(/^\bIF\b\s+/i,"");
a[i]=a[i].replace(/\bTHEN$\b/i,"");
a[i]=a[i].replace(/=/g,"==").replace(/<>/g,"!="); //TODO: it should not replace if inside a string! <---------------
a[i]=a[i].replace(/\bOR\b/gi,"||").replace(/\bAND\b/gi,"&&"); //TODO: it should not replace if inside a string! <---------------
a[i] = "if(" + a[i] + "){";
//ELSE
}else if(a[i].search(/^ELSE/i)>-1){
a[i] = "}else{";
//END IF
}else if(a[i].search(/^END\s*IF/i)>-1){
a[i] = "}";
//WHILE
}else if(a[i].search(/^WHILE\s/i)>-1){
a[i] = a[i].replace(/^WHILE(.+)/i,"while($1){");
//WEND
}else if(a[i].search(/^WEND/i)>-1){
a[i] = "}";
//DO WHILE
}else if(a[i].search(/^DO\s+WHILE\s/i)>-1){
a[i] = a[i].replace(/^DO\s+WHILE(.+)/i,"while($1){");
//LOOP
}else if(a[i].search(/^LOOP$/i)>-1){
a[i] = "}";
//EXIT FUNCTION
}else if(a[i].search(/\bEXIT\b\s*\bFUNCTION\b/i)>-1){
a[i] = "return";
//SELECT CASE
}else if(a[i].search(/^SELECT\s+CASE(.+$)/i)>-1){
a[i]=a[i].replace(/^SELECT\s+CASE(.+$)/i,"switch($1){");
}else if(a[i].search(/^END\s+SELECT/i)>-1){
a[i] = "}";
}else if(a[i].search(/^CASE\s+ELSE/i)>-1){
a[i] = "default:";
}else if(a[i].search(/^CASE[\w\W]+$/i)>-1){
a[i] = a[i] + ":" ;
}
//CONST
else if(a[i].search(/^CONST/i)>-1){
a[i] = a[i].replace(/^CONST/i,"const");
}
else{
//alert(a[i]);
}
//COMMENT
if(a[i].search(/^\'/)>-1){
a[i]=a[i].replace(/^\'/,"//");
}else if(a[i].search(/\'.*$/)>-1){
a[i]=a[i].replace(/\'(.*)$/,"//$1");
}
}
//alert(a.join("*"));
Vars = Vars.replace(/\s*AS\s+\w+\s*/gi,"");
if(Vars!="") Vars = "var " + Vars.replace(/,$/,";").replace(/,/g,", ");
FxHead + '\n' + Vars;
a=a.filter(function(val) { return val !== ""; }) //remove empty items
for(i=0;i<a.length;i++){
if (a[i].search(/[^}{:]$/)>-1) a[i]+=";";
}
ss = FxHead + '\n' + Vars + '\n' + a.join('\n') + '\n}';
ss = ss.replace(new RegExp(Fx+"\\s*=\\s*","gi"),"return ");
ss = UnHideStrings(ss);
return jsIndenter(ss);
}
//-----------------------------------------------------
function jsIndenter(js){
var a=js.split('\n');
var margin=0;
var s = '';
//trim
for(i=0;i<a.length;i++){ a[i]=a[i].replace(/^\s+|\s+$/,""); }
//remove empty items
a=a.filter(function(val) { return val !== ""; });
for(var i=1;i<a.length;i++){
if(a[i-1].indexOf("{")>-1) margin += 4 ;
if(a[i].indexOf("}")>-1) { margin -= 4; }
if(margin<0) margin = 0;
a[i] = StrFill(margin," ") + a[i] ;
}
return a.join('\n');
}
function StrFill(Count,StrToFill){
var objStr,idx;
if(StrToFill=="" || Count==0){
return "";
}
objStr="";
for(idx=1;idx<=Count;idx++){
objStr += StrToFill;
}
return objStr;
}
function HideStrings(text){
const x = String.fromCharCode(7);
const xxx = String.fromCharCode(8);
text = text.replace(/"""/gim, '"'+xxx); //hide 3 quotes " " "
var idx=0, f=0;
while(f>-1){
f = text.search(/".+?"/gim);
if(f>-1){
strs.push(text.match(/".+?"/)[0]);
//alert(strs[idx]);
text = text.replace(/".+?"/, x+idx+x);
idx++;
}
}
//alert(text);
return text;
}
function UnHideStrings(text){
for(var i=0; i<strs.length; i++){
text = text.replace(new RegExp("\\x07"+i+"\\x07"), strs[i]);
}
//Unhide 3 quotes " " " ***BUG: causes unterminated string if triple-quotes are at the end of the string
text = text.replace(/\x08/gim,'\\"');
text = text.replace(/""/gi,'\\"');
return text;
}
The proper way to parse source code for any programming language is to use a parser. Regular expressions are a useful part of (some) parsers, but a parser is a different sort of thing. There is quite a body of research and techniques in the Computer Science literature on the subject of parsing, and it's a fascinating pursuit to study.
"Converting" a bunch of Visual Basic code to Javascript is a project that seems inherently fraught with peril and mystery. A Visual Basic parser will be just the first significant hurdle to conquer. After that, you'll need to figure out how to semantically represent the Visual Basic operations in Javascript. Depending on the original context of the code, that could be somewhat weird. (You don't mention anything about where this code all runs.)
As enriching a learning experience as this might be, it's not unlikely that translating the code by hand will (in the end) take less time and produce better results. That's particularly true if you're just now finding out that there is such a thing as a "parser".
Nice job. Sounds like you did something that might not be perfect, but it did the job.
I'd recommend looking into parsers and grammars if you want to make it more sophisticated. There are lots of parser generators that would be able to help you. You'd have to come up with a grammar for the source language, generate the lexer/parser, and then use that to generate an abstract syntax tree (AST). Once you have that, you can walk the AST and ask it to emit any code you want.
It's doable but, as Oded says, it's not trivial.
I have a friend who has an assignment on arrays and because I lack experience in Javascript and she just needs some real quick help understanding how to implement a Javascript loop to store data in an array which converts a letter grade to a number. Can someone just guide her in a general direction?
https://docs.google.com/fileview?id=16uNNiooLalkm1QlszrqEPr2qqMGLjhrtQx7qCLw-7d2ftygre8GM6hyceJHj&hl=en\
Update: She states that she doesn't understand how to make it prompt again after the first time while storing data. Can someone just write a translation for a C++ code for do {}?
Here's a more or less complete solution - but it doesn't output the results to the HTML page but outputs it with the alert boxes.
var done = false,
classes = [],
total_credits = 0,
avg = 0;
while(!done){
var class_name = prompt("Enter class name"),
letter_grade = prompt("Enter letter grade for "+class_name),
credit_hours = prompt("Enter credit hours for "+class_name),
number_grade = {"A":4,"B":3,"C":2,"D":1,"F":0}[letter_grade];
if(class_name && letter_grade && credit_hours){
classes.push({
class_name: class_name,
letter_grade: letter_grade,
number_grade: number_grade,
credit_hours: credit_hours
});
total_credits += parseInt(credit_hours,10);
avg += number_grade*credit_hours;
}else
done = true;
}
avg = avg/total_credits;
for(var i=0; i<classes.length; i++){
alert(classes[i].class_name + " | " +
classes[i].letter_grade + " | " +
classes[i].credit_hours);
}
alert("Total credits: " + total_credits);
alert("GPA: " + avg.toFixed(2));
Basically, she should use a while loop.
in (mostly) pseudocode:
more_entries = true;
while(more_entries)
{
response = prompt("Question for the user","");
if (response == null)
{
more_entries = false;
}
else
{
// store value somewhere
}
}
Of course, this needs to be expanded to multiple prompts.